diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-02-24 15:18:05 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-02-24 15:18:05 -0500 |
commit | 17162a117cd0733ad1db728fa804e62ded9a87d6 (patch) | |
tree | 24339c44f10e0d524baabb4bd7535f9dd42ec872 | |
parent | 8cbd468bdeb5ed3acac2d7a9f7494d5b77e46297 (diff) | |
parent | 1222d527f314c86a3b59a522115d62facc5a7965 (diff) |
Merge back earlier cpufreq material for v5.1.
36 files changed, 778 insertions, 301 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index 41ce5f4ad838..3f2c6d697cab 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -1737,6 +1737,7 @@ F: arch/arm/configs/mvebu_*_defconfig | |||
1737 | F: arch/arm/mach-mvebu/ | 1737 | F: arch/arm/mach-mvebu/ |
1738 | F: arch/arm64/boot/dts/marvell/armada* | 1738 | F: arch/arm64/boot/dts/marvell/armada* |
1739 | F: drivers/cpufreq/armada-37xx-cpufreq.c | 1739 | F: drivers/cpufreq/armada-37xx-cpufreq.c |
1740 | F: drivers/cpufreq/armada-8k-cpufreq.c | ||
1740 | F: drivers/cpufreq/mvebu-cpufreq.c | 1741 | F: drivers/cpufreq/mvebu-cpufreq.c |
1741 | F: drivers/irqchip/irq-armada-370-xp.c | 1742 | F: drivers/irqchip/irq-armada-370-xp.c |
1742 | F: drivers/irqchip/irq-mvebu-* | 1743 | F: drivers/irqchip/irq-mvebu-* |
@@ -3961,7 +3962,7 @@ M: Viresh Kumar <viresh.kumar@linaro.org> | |||
3961 | L: linux-pm@vger.kernel.org | 3962 | L: linux-pm@vger.kernel.org |
3962 | S: Maintained | 3963 | S: Maintained |
3963 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git | 3964 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git |
3964 | T: git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates) | 3965 | T: git git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm.git (For ARM Updates) |
3965 | B: https://bugzilla.kernel.org | 3966 | B: https://bugzilla.kernel.org |
3966 | F: Documentation/admin-guide/pm/cpufreq.rst | 3967 | F: Documentation/admin-guide/pm/cpufreq.rst |
3967 | F: Documentation/admin-guide/pm/intel_pstate.rst | 3968 | F: Documentation/admin-guide/pm/intel_pstate.rst |
@@ -12604,11 +12605,11 @@ F: Documentation/media/v4l-drivers/qcom_camss.rst | |||
12604 | F: drivers/media/platform/qcom/camss/ | 12605 | F: drivers/media/platform/qcom/camss/ |
12605 | 12606 | ||
12606 | QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096 | 12607 | QUALCOMM CPUFREQ DRIVER MSM8996/APQ8096 |
12607 | M: Ilia Lin <ilia.lin@gmail.com> | 12608 | M: Ilia Lin <ilia.lin@kernel.org> |
12608 | L: linux-pm@vger.kernel.org | 12609 | L: linux-pm@vger.kernel.org |
12609 | S: Maintained | 12610 | S: Maintained |
12610 | F: Documentation/devicetree/bindings/opp/kryo-cpufreq.txt | 12611 | F: Documentation/devicetree/bindings/opp/kryo-cpufreq.txt |
12611 | F: drivers/cpufreq/qcom-cpufreq-kryo.c | 12612 | F: drivers/cpufreq/qcom-cpufreq-kryo.c |
12612 | 12613 | ||
12613 | QUALCOMM EMAC GIGABIT ETHERNET DRIVER | 12614 | QUALCOMM EMAC GIGABIT ETHERNET DRIVER |
12614 | M: Timur Tabi <timur@kernel.org> | 12615 | M: Timur Tabi <timur@kernel.org> |
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c index e7b78df2bfef..a02ff431ba47 100644 --- a/arch/arm/mach-davinci/da850.c +++ b/arch/arm/mach-davinci/da850.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/mfd/da8xx-cfgchip.h> | 21 | #include <linux/mfd/da8xx-cfgchip.h> |
22 | #include <linux/platform_data/clk-da8xx-cfgchip.h> | 22 | #include <linux/platform_data/clk-da8xx-cfgchip.h> |
23 | #include <linux/platform_data/clk-davinci-pll.h> | 23 | #include <linux/platform_data/clk-davinci-pll.h> |
24 | #include <linux/platform_data/davinci-cpufreq.h> | ||
24 | #include <linux/platform_data/gpio-davinci.h> | 25 | #include <linux/platform_data/gpio-davinci.h> |
25 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
26 | #include <linux/regmap.h> | 27 | #include <linux/regmap.h> |
@@ -29,7 +30,6 @@ | |||
29 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
30 | 31 | ||
31 | #include <mach/common.h> | 32 | #include <mach/common.h> |
32 | #include <mach/cpufreq.h> | ||
33 | #include <mach/cputype.h> | 33 | #include <mach/cputype.h> |
34 | #include <mach/da8xx.h> | 34 | #include <mach/da8xx.h> |
35 | #include <mach/irqs.h> | 35 | #include <mach/irqs.h> |
diff --git a/arch/arm/mach-davinci/include/mach/cpufreq.h b/arch/arm/mach-davinci/include/mach/cpufreq.h deleted file mode 100644 index 3c089cfb6cd6..000000000000 --- a/arch/arm/mach-davinci/include/mach/cpufreq.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * TI DaVinci CPUFreq platform support. | ||
3 | * | ||
4 | * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.com/ | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License as | ||
8 | * published by the Free Software Foundation version 2. | ||
9 | * | ||
10 | * This program is distributed "as is" WITHOUT ANY WARRANTY of any | ||
11 | * kind, whether express or implied; without even the implied warranty | ||
12 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | #ifndef _MACH_DAVINCI_CPUFREQ_H | ||
16 | #define _MACH_DAVINCI_CPUFREQ_H | ||
17 | |||
18 | #include <linux/cpufreq.h> | ||
19 | |||
20 | struct davinci_cpufreq_config { | ||
21 | struct cpufreq_frequency_table *freq_table; | ||
22 | int (*set_voltage) (unsigned int index); | ||
23 | int (*init) (void); | ||
24 | }; | ||
25 | |||
26 | #endif | ||
diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c index 217a782c3e55..1b207fca1420 100644 --- a/drivers/acpi/cppc_acpi.c +++ b/drivers/acpi/cppc_acpi.c | |||
@@ -1051,6 +1051,48 @@ static int cpc_write(int cpu, struct cpc_register_resource *reg_res, u64 val) | |||
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | /** | 1053 | /** |
1054 | * cppc_get_desired_perf - Get the value of desired performance register. | ||
1055 | * @cpunum: CPU from which to get desired performance. | ||
1056 | * @desired_perf: address of a variable to store the returned desired performance | ||
1057 | * | ||
1058 | * Return: 0 for success, -EIO otherwise. | ||
1059 | */ | ||
1060 | int cppc_get_desired_perf(int cpunum, u64 *desired_perf) | ||
1061 | { | ||
1062 | struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum); | ||
1063 | int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, cpunum); | ||
1064 | struct cpc_register_resource *desired_reg; | ||
1065 | struct cppc_pcc_data *pcc_ss_data = NULL; | ||
1066 | |||
1067 | desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF]; | ||
1068 | |||
1069 | if (CPC_IN_PCC(desired_reg)) { | ||
1070 | int ret = 0; | ||
1071 | |||
1072 | if (pcc_ss_id < 0) | ||
1073 | return -EIO; | ||
1074 | |||
1075 | pcc_ss_data = pcc_data[pcc_ss_id]; | ||
1076 | |||
1077 | down_write(&pcc_ss_data->pcc_lock); | ||
1078 | |||
1079 | if (send_pcc_cmd(pcc_ss_id, CMD_READ) >= 0) | ||
1080 | cpc_read(cpunum, desired_reg, desired_perf); | ||
1081 | else | ||
1082 | ret = -EIO; | ||
1083 | |||
1084 | up_write(&pcc_ss_data->pcc_lock); | ||
1085 | |||
1086 | return ret; | ||
1087 | } | ||
1088 | |||
1089 | cpc_read(cpunum, desired_reg, desired_perf); | ||
1090 | |||
1091 | return 0; | ||
1092 | } | ||
1093 | EXPORT_SYMBOL_GPL(cppc_get_desired_perf); | ||
1094 | |||
1095 | /** | ||
1054 | * cppc_get_perf_caps - Get a CPUs performance capabilities. | 1096 | * cppc_get_perf_caps - Get a CPUs performance capabilities. |
1055 | * @cpunum: CPU from which to get capabilities info. | 1097 | * @cpunum: CPU from which to get capabilities info. |
1056 | * @perf_caps: ptr to cppc_perf_caps. See cppc_acpi.h | 1098 | * @perf_caps: ptr to cppc_perf_caps. See cppc_acpi.h |
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index 608af20a3494..b22e6bba71f1 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig | |||
@@ -207,8 +207,6 @@ comment "CPU frequency scaling drivers" | |||
207 | config CPUFREQ_DT | 207 | config CPUFREQ_DT |
208 | tristate "Generic DT based cpufreq driver" | 208 | tristate "Generic DT based cpufreq driver" |
209 | depends on HAVE_CLK && OF | 209 | depends on HAVE_CLK && OF |
210 | # if CPU_THERMAL is on and THERMAL=m, CPUFREQ_DT cannot be =y: | ||
211 | depends on !CPU_THERMAL || THERMAL | ||
212 | select CPUFREQ_DT_PLATDEV | 210 | select CPUFREQ_DT_PLATDEV |
213 | select PM_OPP | 211 | select PM_OPP |
214 | help | 212 | help |
@@ -327,7 +325,6 @@ endif | |||
327 | config QORIQ_CPUFREQ | 325 | config QORIQ_CPUFREQ |
328 | tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" | 326 | tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" |
329 | depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64) | 327 | depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64) |
330 | depends on !CPU_THERMAL || THERMAL | ||
331 | select CLK_QORIQ | 328 | select CLK_QORIQ |
332 | help | 329 | help |
333 | This adds the CPUFreq driver support for Freescale QorIQ SoCs | 330 | This adds the CPUFreq driver support for Freescale QorIQ SoCs |
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index 688f10227793..f08bb0075316 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm | |||
@@ -25,12 +25,21 @@ config ARM_ARMADA_37XX_CPUFREQ | |||
25 | This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. | 25 | This adds the CPUFreq driver support for Marvell Armada 37xx SoCs. |
26 | The Armada 37xx PMU supports 4 frequency and VDD levels. | 26 | The Armada 37xx PMU supports 4 frequency and VDD levels. |
27 | 27 | ||
28 | config ARM_ARMADA_8K_CPUFREQ | ||
29 | tristate "Armada 8K CPUFreq driver" | ||
30 | depends on ARCH_MVEBU && CPUFREQ_DT | ||
31 | help | ||
32 | This enables the CPUFreq driver support for Marvell | ||
33 | Armada8k SOCs. | ||
34 | Armada8K device has the AP806 which supports scaling | ||
35 | to any full integer divider. | ||
36 | |||
37 | If in doubt, say N. | ||
38 | |||
28 | # big LITTLE core layer and glue drivers | 39 | # big LITTLE core layer and glue drivers |
29 | config ARM_BIG_LITTLE_CPUFREQ | 40 | config ARM_BIG_LITTLE_CPUFREQ |
30 | tristate "Generic ARM big LITTLE CPUfreq driver" | 41 | tristate "Generic ARM big LITTLE CPUfreq driver" |
31 | depends on ARM_CPU_TOPOLOGY && HAVE_CLK | 42 | depends on ARM_CPU_TOPOLOGY && HAVE_CLK |
32 | # if CPU_THERMAL is on and THERMAL=m, ARM_BIT_LITTLE_CPUFREQ cannot be =y | ||
33 | depends on !CPU_THERMAL || THERMAL | ||
34 | select PM_OPP | 43 | select PM_OPP |
35 | help | 44 | help |
36 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. | 45 | This enables the Generic CPUfreq driver for ARM big.LITTLE platforms. |
@@ -38,7 +47,6 @@ config ARM_BIG_LITTLE_CPUFREQ | |||
38 | config ARM_SCPI_CPUFREQ | 47 | config ARM_SCPI_CPUFREQ |
39 | tristate "SCPI based CPUfreq driver" | 48 | tristate "SCPI based CPUfreq driver" |
40 | depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI | 49 | depends on ARM_SCPI_PROTOCOL && COMMON_CLK_SCPI |
41 | depends on !CPU_THERMAL || THERMAL | ||
42 | help | 50 | help |
43 | This adds the CPUfreq driver support for ARM platforms using SCPI | 51 | This adds the CPUfreq driver support for ARM platforms using SCPI |
44 | protocol for CPU power management. | 52 | protocol for CPU power management. |
@@ -93,7 +101,6 @@ config ARM_KIRKWOOD_CPUFREQ | |||
93 | config ARM_MEDIATEK_CPUFREQ | 101 | config ARM_MEDIATEK_CPUFREQ |
94 | tristate "CPU Frequency scaling support for MediaTek SoCs" | 102 | tristate "CPU Frequency scaling support for MediaTek SoCs" |
95 | depends on ARCH_MEDIATEK && REGULATOR | 103 | depends on ARCH_MEDIATEK && REGULATOR |
96 | depends on !CPU_THERMAL || THERMAL | ||
97 | select PM_OPP | 104 | select PM_OPP |
98 | help | 105 | help |
99 | This adds the CPUFreq driver support for MediaTek SoCs. | 106 | This adds the CPUFreq driver support for MediaTek SoCs. |
@@ -233,7 +240,6 @@ config ARM_SA1110_CPUFREQ | |||
233 | config ARM_SCMI_CPUFREQ | 240 | config ARM_SCMI_CPUFREQ |
234 | tristate "SCMI based CPUfreq driver" | 241 | tristate "SCMI based CPUfreq driver" |
235 | depends on ARM_SCMI_PROTOCOL || COMPILE_TEST | 242 | depends on ARM_SCMI_PROTOCOL || COMPILE_TEST |
236 | depends on !CPU_THERMAL || THERMAL | ||
237 | select PM_OPP | 243 | select PM_OPP |
238 | help | 244 | help |
239 | This adds the CPUfreq driver support for ARM platforms using SCMI | 245 | This adds the CPUfreq driver support for ARM platforms using SCMI |
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 08c071be2491..689b26c6f949 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile | |||
@@ -50,6 +50,7 @@ obj-$(CONFIG_X86_SFI_CPUFREQ) += sfi-cpufreq.o | |||
50 | obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o | 50 | obj-$(CONFIG_ARM_BIG_LITTLE_CPUFREQ) += arm_big_little.o |
51 | 51 | ||
52 | obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o | 52 | obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o |
53 | obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o | ||
53 | obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o | 54 | obj-$(CONFIG_ARM_BRCMSTB_AVS_CPUFREQ) += brcmstb-avs-cpufreq.o |
54 | obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o | 55 | obj-$(CONFIG_ACPI_CPPC_CPUFREQ) += cppc_cpufreq.o |
55 | obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o | 56 | obj-$(CONFIG_ARCH_DAVINCI) += davinci-cpufreq.o |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index d62fd374d5c7..c72258a44ba4 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -916,8 +916,10 @@ static void __init acpi_cpufreq_boost_init(void) | |||
916 | { | 916 | { |
917 | int ret; | 917 | int ret; |
918 | 918 | ||
919 | if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA))) | 919 | if (!(boot_cpu_has(X86_FEATURE_CPB) || boot_cpu_has(X86_FEATURE_IDA))) { |
920 | pr_debug("Boost capabilities not present in the processor\n"); | ||
920 | return; | 921 | return; |
922 | } | ||
921 | 923 | ||
922 | acpi_cpufreq_driver.set_boost = set_boost; | 924 | acpi_cpufreq_driver.set_boost = set_boost; |
923 | acpi_cpufreq_driver.boost_enabled = boost_state(0); | 925 | acpi_cpufreq_driver.boost_enabled = boost_state(0); |
diff --git a/drivers/cpufreq/armada-8k-cpufreq.c b/drivers/cpufreq/armada-8k-cpufreq.c new file mode 100644 index 000000000000..8a5ddb93fc58 --- /dev/null +++ b/drivers/cpufreq/armada-8k-cpufreq.c | |||
@@ -0,0 +1,204 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0+ | ||
2 | /* | ||
3 | * CPUFreq support for Armada 8K | ||
4 | * | ||
5 | * Copyright (C) 2018 Marvell | ||
6 | * | ||
7 | * Omri Itach <omrii@marvell.com> | ||
8 | * Gregory Clement <gregory.clement@bootlin.com> | ||
9 | */ | ||
10 | |||
11 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
12 | |||
13 | #include <linux/clk.h> | ||
14 | #include <linux/cpu.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/init.h> | ||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/of.h> | ||
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/pm_opp.h> | ||
22 | #include <linux/slab.h> | ||
23 | |||
24 | /* | ||
25 | * Setup the opps list with the divider for the max frequency, that | ||
26 | * will be filled at runtime. | ||
27 | */ | ||
28 | static const int opps_div[] __initconst = {1, 2, 3, 4}; | ||
29 | |||
30 | static struct platform_device *armada_8k_pdev; | ||
31 | |||
32 | struct freq_table { | ||
33 | struct device *cpu_dev; | ||
34 | unsigned int freq[ARRAY_SIZE(opps_div)]; | ||
35 | }; | ||
36 | |||
37 | /* If the CPUs share the same clock, then they are in the same cluster. */ | ||
38 | static void __init armada_8k_get_sharing_cpus(struct clk *cur_clk, | ||
39 | struct cpumask *cpumask) | ||
40 | { | ||
41 | int cpu; | ||
42 | |||
43 | for_each_possible_cpu(cpu) { | ||
44 | struct device *cpu_dev; | ||
45 | struct clk *clk; | ||
46 | |||
47 | cpu_dev = get_cpu_device(cpu); | ||
48 | if (!cpu_dev) { | ||
49 | pr_warn("Failed to get cpu%d device\n", cpu); | ||
50 | continue; | ||
51 | } | ||
52 | |||
53 | clk = clk_get(cpu_dev, 0); | ||
54 | if (IS_ERR(clk)) { | ||
55 | pr_warn("Cannot get clock for CPU %d\n", cpu); | ||
56 | } else { | ||
57 | if (clk_is_match(clk, cur_clk)) | ||
58 | cpumask_set_cpu(cpu, cpumask); | ||
59 | |||
60 | clk_put(clk); | ||
61 | } | ||
62 | } | ||
63 | } | ||
64 | |||
65 | static int __init armada_8k_add_opp(struct clk *clk, struct device *cpu_dev, | ||
66 | struct freq_table *freq_tables, | ||
67 | int opps_index) | ||
68 | { | ||
69 | unsigned int cur_frequency; | ||
70 | unsigned int freq; | ||
71 | int i, ret; | ||
72 | |||
73 | /* Get nominal (current) CPU frequency. */ | ||
74 | cur_frequency = clk_get_rate(clk); | ||
75 | if (!cur_frequency) { | ||
76 | dev_err(cpu_dev, "Failed to get clock rate for this CPU\n"); | ||
77 | return -EINVAL; | ||
78 | } | ||
79 | |||
80 | freq_tables[opps_index].cpu_dev = cpu_dev; | ||
81 | |||
82 | for (i = 0; i < ARRAY_SIZE(opps_div); i++) { | ||
83 | freq = cur_frequency / opps_div[i]; | ||
84 | |||
85 | ret = dev_pm_opp_add(cpu_dev, freq, 0); | ||
86 | if (ret) | ||
87 | return ret; | ||
88 | |||
89 | freq_tables[opps_index].freq[i] = freq; | ||
90 | } | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static void armada_8k_cpufreq_free_table(struct freq_table *freq_tables) | ||
96 | { | ||
97 | int opps_index, nb_cpus = num_possible_cpus(); | ||
98 | |||
99 | for (opps_index = 0 ; opps_index <= nb_cpus; opps_index++) { | ||
100 | int i; | ||
101 | |||
102 | /* If cpu_dev is NULL then we reached the end of the array */ | ||
103 | if (!freq_tables[opps_index].cpu_dev) | ||
104 | break; | ||
105 | |||
106 | for (i = 0; i < ARRAY_SIZE(opps_div); i++) { | ||
107 | /* | ||
108 | * A 0Hz frequency is not valid, this meant | ||
109 | * that it was not yet initialized so there is | ||
110 | * no more opp to free | ||
111 | */ | ||
112 | if (freq_tables[opps_index].freq[i] == 0) | ||
113 | break; | ||
114 | |||
115 | dev_pm_opp_remove(freq_tables[opps_index].cpu_dev, | ||
116 | freq_tables[opps_index].freq[i]); | ||
117 | } | ||
118 | } | ||
119 | |||
120 | kfree(freq_tables); | ||
121 | } | ||
122 | |||
123 | static int __init armada_8k_cpufreq_init(void) | ||
124 | { | ||
125 | int ret = 0, opps_index = 0, cpu, nb_cpus; | ||
126 | struct freq_table *freq_tables; | ||
127 | struct device_node *node; | ||
128 | struct cpumask cpus; | ||
129 | |||
130 | node = of_find_compatible_node(NULL, NULL, "marvell,ap806-cpu-clock"); | ||
131 | if (!node || !of_device_is_available(node)) | ||
132 | return -ENODEV; | ||
133 | |||
134 | nb_cpus = num_possible_cpus(); | ||
135 | freq_tables = kcalloc(nb_cpus, sizeof(*freq_tables), GFP_KERNEL); | ||
136 | cpumask_copy(&cpus, cpu_possible_mask); | ||
137 | |||
138 | /* | ||
139 | * For each CPU, this loop registers the operating points | ||
140 | * supported (which are the nominal CPU frequency and full integer | ||
141 | * divisions of it). | ||
142 | */ | ||
143 | for_each_cpu(cpu, &cpus) { | ||
144 | struct cpumask shared_cpus; | ||
145 | struct device *cpu_dev; | ||
146 | struct clk *clk; | ||
147 | |||
148 | cpu_dev = get_cpu_device(cpu); | ||
149 | |||
150 | if (!cpu_dev) { | ||
151 | pr_err("Cannot get CPU %d\n", cpu); | ||
152 | continue; | ||
153 | } | ||
154 | |||
155 | clk = clk_get(cpu_dev, 0); | ||
156 | |||
157 | if (IS_ERR(clk)) { | ||
158 | pr_err("Cannot get clock for CPU %d\n", cpu); | ||
159 | ret = PTR_ERR(clk); | ||
160 | goto remove_opp; | ||
161 | } | ||
162 | |||
163 | ret = armada_8k_add_opp(clk, cpu_dev, freq_tables, opps_index); | ||
164 | if (ret) { | ||
165 | clk_put(clk); | ||
166 | goto remove_opp; | ||
167 | } | ||
168 | |||
169 | opps_index++; | ||
170 | cpumask_clear(&shared_cpus); | ||
171 | armada_8k_get_sharing_cpus(clk, &shared_cpus); | ||
172 | dev_pm_opp_set_sharing_cpus(cpu_dev, &shared_cpus); | ||
173 | cpumask_andnot(&cpus, &cpus, &shared_cpus); | ||
174 | clk_put(clk); | ||
175 | } | ||
176 | |||
177 | armada_8k_pdev = platform_device_register_simple("cpufreq-dt", -1, | ||
178 | NULL, 0); | ||
179 | ret = PTR_ERR_OR_ZERO(armada_8k_pdev); | ||
180 | if (ret) | ||
181 | goto remove_opp; | ||
182 | |||
183 | platform_set_drvdata(armada_8k_pdev, freq_tables); | ||
184 | |||
185 | return 0; | ||
186 | |||
187 | remove_opp: | ||
188 | armada_8k_cpufreq_free_table(freq_tables); | ||
189 | return ret; | ||
190 | } | ||
191 | module_init(armada_8k_cpufreq_init); | ||
192 | |||
193 | static void __exit armada_8k_cpufreq_exit(void) | ||
194 | { | ||
195 | struct freq_table *freq_tables = platform_get_drvdata(armada_8k_pdev); | ||
196 | |||
197 | platform_device_unregister(armada_8k_pdev); | ||
198 | armada_8k_cpufreq_free_table(freq_tables); | ||
199 | } | ||
200 | module_exit(armada_8k_cpufreq_exit); | ||
201 | |||
202 | MODULE_AUTHOR("Gregory Clement <gregory.clement@bootlin.com>"); | ||
203 | MODULE_DESCRIPTION("Armada 8K cpufreq driver"); | ||
204 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c index fd25c21cee72..2ae978d27e61 100644 --- a/drivers/cpufreq/cppc_cpufreq.c +++ b/drivers/cpufreq/cppc_cpufreq.c | |||
@@ -42,6 +42,66 @@ | |||
42 | */ | 42 | */ |
43 | static struct cppc_cpudata **all_cpu_data; | 43 | static struct cppc_cpudata **all_cpu_data; |
44 | 44 | ||
45 | struct cppc_workaround_oem_info { | ||
46 | char oem_id[ACPI_OEM_ID_SIZE +1]; | ||
47 | char oem_table_id[ACPI_OEM_TABLE_ID_SIZE + 1]; | ||
48 | u32 oem_revision; | ||
49 | }; | ||
50 | |||
51 | static bool apply_hisi_workaround; | ||
52 | |||
53 | static struct cppc_workaround_oem_info wa_info[] = { | ||
54 | { | ||
55 | .oem_id = "HISI ", | ||
56 | .oem_table_id = "HIP07 ", | ||
57 | .oem_revision = 0, | ||
58 | }, { | ||
59 | .oem_id = "HISI ", | ||
60 | .oem_table_id = "HIP08 ", | ||
61 | .oem_revision = 0, | ||
62 | } | ||
63 | }; | ||
64 | |||
65 | static unsigned int cppc_cpufreq_perf_to_khz(struct cppc_cpudata *cpu, | ||
66 | unsigned int perf); | ||
67 | |||
68 | /* | ||
69 | * HISI platform does not support delivered performance counter and | ||
70 | * reference performance counter. It can calculate the performance using the | ||
71 | * platform specific mechanism. We reuse the desired performance register to | ||
72 | * store the real performance calculated by the platform. | ||
73 | */ | ||
74 | static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpunum) | ||
75 | { | ||
76 | struct cppc_cpudata *cpudata = all_cpu_data[cpunum]; | ||
77 | u64 desired_perf; | ||
78 | int ret; | ||
79 | |||
80 | ret = cppc_get_desired_perf(cpunum, &desired_perf); | ||
81 | if (ret < 0) | ||
82 | return -EIO; | ||
83 | |||
84 | return cppc_cpufreq_perf_to_khz(cpudata, desired_perf); | ||
85 | } | ||
86 | |||
87 | static void cppc_check_hisi_workaround(void) | ||
88 | { | ||
89 | struct acpi_table_header *tbl; | ||
90 | acpi_status status = AE_OK; | ||
91 | int i; | ||
92 | |||
93 | status = acpi_get_table(ACPI_SIG_PCCT, 0, &tbl); | ||
94 | if (ACPI_FAILURE(status) || !tbl) | ||
95 | return; | ||
96 | |||
97 | for (i = 0; i < ARRAY_SIZE(wa_info); i++) { | ||
98 | if (!memcmp(wa_info[i].oem_id, tbl->oem_id, ACPI_OEM_ID_SIZE) && | ||
99 | !memcmp(wa_info[i].oem_table_id, tbl->oem_table_id, ACPI_OEM_TABLE_ID_SIZE) && | ||
100 | wa_info[i].oem_revision == tbl->oem_revision) | ||
101 | apply_hisi_workaround = true; | ||
102 | } | ||
103 | } | ||
104 | |||
45 | /* Callback function used to retrieve the max frequency from DMI */ | 105 | /* Callback function used to retrieve the max frequency from DMI */ |
46 | static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private) | 106 | static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private) |
47 | { | 107 | { |
@@ -334,6 +394,9 @@ static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum) | |||
334 | struct cppc_cpudata *cpu = all_cpu_data[cpunum]; | 394 | struct cppc_cpudata *cpu = all_cpu_data[cpunum]; |
335 | int ret; | 395 | int ret; |
336 | 396 | ||
397 | if (apply_hisi_workaround) | ||
398 | return hisi_cppc_cpufreq_get_rate(cpunum); | ||
399 | |||
337 | ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); | 400 | ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0); |
338 | if (ret) | 401 | if (ret) |
339 | return ret; | 402 | return ret; |
@@ -386,6 +449,8 @@ static int __init cppc_cpufreq_init(void) | |||
386 | goto out; | 449 | goto out; |
387 | } | 450 | } |
388 | 451 | ||
452 | cppc_check_hisi_workaround(); | ||
453 | |||
389 | ret = cpufreq_register_driver(&cppc_cpufreq_driver); | 454 | ret = cpufreq_register_driver(&cppc_cpufreq_driver); |
390 | if (ret) | 455 | if (ret) |
391 | goto out; | 456 | goto out; |
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index e58bfcb1169e..1aefaa1b0ca2 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c | |||
@@ -13,7 +13,6 @@ | |||
13 | 13 | ||
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/cpu.h> | 15 | #include <linux/cpu.h> |
16 | #include <linux/cpu_cooling.h> | ||
17 | #include <linux/cpufreq.h> | 16 | #include <linux/cpufreq.h> |
18 | #include <linux/cpumask.h> | 17 | #include <linux/cpumask.h> |
19 | #include <linux/err.h> | 18 | #include <linux/err.h> |
@@ -30,7 +29,6 @@ | |||
30 | struct private_data { | 29 | struct private_data { |
31 | struct opp_table *opp_table; | 30 | struct opp_table *opp_table; |
32 | struct device *cpu_dev; | 31 | struct device *cpu_dev; |
33 | struct thermal_cooling_device *cdev; | ||
34 | const char *reg_name; | 32 | const char *reg_name; |
35 | bool have_static_opps; | 33 | bool have_static_opps; |
36 | }; | 34 | }; |
@@ -297,11 +295,25 @@ out_put_clk: | |||
297 | return ret; | 295 | return ret; |
298 | } | 296 | } |
299 | 297 | ||
298 | static int cpufreq_online(struct cpufreq_policy *policy) | ||
299 | { | ||
300 | /* We did light-weight tear down earlier, nothing to do here */ | ||
301 | return 0; | ||
302 | } | ||
303 | |||
304 | static int cpufreq_offline(struct cpufreq_policy *policy) | ||
305 | { | ||
306 | /* | ||
307 | * Preserve policy->driver_data and don't free resources on light-weight | ||
308 | * tear down. | ||
309 | */ | ||
310 | return 0; | ||
311 | } | ||
312 | |||
300 | static int cpufreq_exit(struct cpufreq_policy *policy) | 313 | static int cpufreq_exit(struct cpufreq_policy *policy) |
301 | { | 314 | { |
302 | struct private_data *priv = policy->driver_data; | 315 | struct private_data *priv = policy->driver_data; |
303 | 316 | ||
304 | cpufreq_cooling_unregister(priv->cdev); | ||
305 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); | 317 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); |
306 | if (priv->have_static_opps) | 318 | if (priv->have_static_opps) |
307 | dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); | 319 | dev_pm_opp_of_cpumask_remove_table(policy->related_cpus); |
@@ -314,21 +326,16 @@ static int cpufreq_exit(struct cpufreq_policy *policy) | |||
314 | return 0; | 326 | return 0; |
315 | } | 327 | } |
316 | 328 | ||
317 | static void cpufreq_ready(struct cpufreq_policy *policy) | ||
318 | { | ||
319 | struct private_data *priv = policy->driver_data; | ||
320 | |||
321 | priv->cdev = of_cpufreq_cooling_register(policy); | ||
322 | } | ||
323 | |||
324 | static struct cpufreq_driver dt_cpufreq_driver = { | 329 | static struct cpufreq_driver dt_cpufreq_driver = { |
325 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | 330 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
331 | CPUFREQ_IS_COOLING_DEV, | ||
326 | .verify = cpufreq_generic_frequency_table_verify, | 332 | .verify = cpufreq_generic_frequency_table_verify, |
327 | .target_index = set_target, | 333 | .target_index = set_target, |
328 | .get = cpufreq_generic_get, | 334 | .get = cpufreq_generic_get, |
329 | .init = cpufreq_init, | 335 | .init = cpufreq_init, |
330 | .exit = cpufreq_exit, | 336 | .exit = cpufreq_exit, |
331 | .ready = cpufreq_ready, | 337 | .online = cpufreq_online, |
338 | .offline = cpufreq_offline, | ||
332 | .name = "cpufreq-dt", | 339 | .name = "cpufreq-dt", |
333 | .attr = cpufreq_dt_attr, | 340 | .attr = cpufreq_dt_attr, |
334 | .suspend = cpufreq_generic_suspend, | 341 | .suspend = cpufreq_generic_suspend, |
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e35a886e00bc..0e626b00053b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/cpu.h> | 20 | #include <linux/cpu.h> |
21 | #include <linux/cpufreq.h> | 21 | #include <linux/cpufreq.h> |
22 | #include <linux/cpu_cooling.h> | ||
22 | #include <linux/delay.h> | 23 | #include <linux/delay.h> |
23 | #include <linux/device.h> | 24 | #include <linux/device.h> |
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
@@ -545,13 +546,13 @@ EXPORT_SYMBOL_GPL(cpufreq_policy_transition_delay_us); | |||
545 | * SYSFS INTERFACE * | 546 | * SYSFS INTERFACE * |
546 | *********************************************************************/ | 547 | *********************************************************************/ |
547 | static ssize_t show_boost(struct kobject *kobj, | 548 | static ssize_t show_boost(struct kobject *kobj, |
548 | struct attribute *attr, char *buf) | 549 | struct kobj_attribute *attr, char *buf) |
549 | { | 550 | { |
550 | return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); | 551 | return sprintf(buf, "%d\n", cpufreq_driver->boost_enabled); |
551 | } | 552 | } |
552 | 553 | ||
553 | static ssize_t store_boost(struct kobject *kobj, struct attribute *attr, | 554 | static ssize_t store_boost(struct kobject *kobj, struct kobj_attribute *attr, |
554 | const char *buf, size_t count) | 555 | const char *buf, size_t count) |
555 | { | 556 | { |
556 | int ret, enable; | 557 | int ret, enable; |
557 | 558 | ||
@@ -1200,28 +1201,39 @@ static int cpufreq_online(unsigned int cpu) | |||
1200 | return -ENOMEM; | 1201 | return -ENOMEM; |
1201 | } | 1202 | } |
1202 | 1203 | ||
1203 | cpumask_copy(policy->cpus, cpumask_of(cpu)); | 1204 | if (!new_policy && cpufreq_driver->online) { |
1205 | ret = cpufreq_driver->online(policy); | ||
1206 | if (ret) { | ||
1207 | pr_debug("%s: %d: initialization failed\n", __func__, | ||
1208 | __LINE__); | ||
1209 | goto out_exit_policy; | ||
1210 | } | ||
1204 | 1211 | ||
1205 | /* call driver. From then on the cpufreq must be able | 1212 | /* Recover policy->cpus using related_cpus */ |
1206 | * to accept all calls to ->verify and ->setpolicy for this CPU | 1213 | cpumask_copy(policy->cpus, policy->related_cpus); |
1207 | */ | 1214 | } else { |
1208 | ret = cpufreq_driver->init(policy); | 1215 | cpumask_copy(policy->cpus, cpumask_of(cpu)); |
1209 | if (ret) { | ||
1210 | pr_debug("initialization failed\n"); | ||
1211 | goto out_free_policy; | ||
1212 | } | ||
1213 | 1216 | ||
1214 | ret = cpufreq_table_validate_and_sort(policy); | 1217 | /* |
1215 | if (ret) | 1218 | * Call driver. From then on the cpufreq must be able |
1216 | goto out_exit_policy; | 1219 | * to accept all calls to ->verify and ->setpolicy for this CPU. |
1220 | */ | ||
1221 | ret = cpufreq_driver->init(policy); | ||
1222 | if (ret) { | ||
1223 | pr_debug("%s: %d: initialization failed\n", __func__, | ||
1224 | __LINE__); | ||
1225 | goto out_free_policy; | ||
1226 | } | ||
1217 | 1227 | ||
1218 | down_write(&policy->rwsem); | 1228 | ret = cpufreq_table_validate_and_sort(policy); |
1229 | if (ret) | ||
1230 | goto out_exit_policy; | ||
1219 | 1231 | ||
1220 | if (new_policy) { | ||
1221 | /* related_cpus should at least include policy->cpus. */ | 1232 | /* related_cpus should at least include policy->cpus. */ |
1222 | cpumask_copy(policy->related_cpus, policy->cpus); | 1233 | cpumask_copy(policy->related_cpus, policy->cpus); |
1223 | } | 1234 | } |
1224 | 1235 | ||
1236 | down_write(&policy->rwsem); | ||
1225 | /* | 1237 | /* |
1226 | * affected cpus must always be the one, which are online. We aren't | 1238 | * affected cpus must always be the one, which are online. We aren't |
1227 | * managing offline cpus here. | 1239 | * managing offline cpus here. |
@@ -1305,8 +1317,6 @@ static int cpufreq_online(unsigned int cpu) | |||
1305 | if (ret) { | 1317 | if (ret) { |
1306 | pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n", | 1318 | pr_err("%s: Failed to initialize policy for cpu: %d (%d)\n", |
1307 | __func__, cpu, ret); | 1319 | __func__, cpu, ret); |
1308 | /* cpufreq_policy_free() will notify based on this */ | ||
1309 | new_policy = false; | ||
1310 | goto out_destroy_policy; | 1320 | goto out_destroy_policy; |
1311 | } | 1321 | } |
1312 | 1322 | ||
@@ -1318,6 +1328,10 @@ static int cpufreq_online(unsigned int cpu) | |||
1318 | if (cpufreq_driver->ready) | 1328 | if (cpufreq_driver->ready) |
1319 | cpufreq_driver->ready(policy); | 1329 | cpufreq_driver->ready(policy); |
1320 | 1330 | ||
1331 | if (IS_ENABLED(CONFIG_CPU_THERMAL) && | ||
1332 | cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) | ||
1333 | policy->cdev = of_cpufreq_cooling_register(policy); | ||
1334 | |||
1321 | pr_debug("initialization complete\n"); | 1335 | pr_debug("initialization complete\n"); |
1322 | 1336 | ||
1323 | return 0; | 1337 | return 0; |
@@ -1405,6 +1419,12 @@ static int cpufreq_offline(unsigned int cpu) | |||
1405 | goto unlock; | 1419 | goto unlock; |
1406 | } | 1420 | } |
1407 | 1421 | ||
1422 | if (IS_ENABLED(CONFIG_CPU_THERMAL) && | ||
1423 | cpufreq_driver->flags & CPUFREQ_IS_COOLING_DEV) { | ||
1424 | cpufreq_cooling_unregister(policy->cdev); | ||
1425 | policy->cdev = NULL; | ||
1426 | } | ||
1427 | |||
1408 | if (cpufreq_driver->stop_cpu) | 1428 | if (cpufreq_driver->stop_cpu) |
1409 | cpufreq_driver->stop_cpu(policy); | 1429 | cpufreq_driver->stop_cpu(policy); |
1410 | 1430 | ||
@@ -1412,11 +1432,12 @@ static int cpufreq_offline(unsigned int cpu) | |||
1412 | cpufreq_exit_governor(policy); | 1432 | cpufreq_exit_governor(policy); |
1413 | 1433 | ||
1414 | /* | 1434 | /* |
1415 | * Perform the ->exit() even during light-weight tear-down, | 1435 | * Perform the ->offline() during light-weight tear-down, as |
1416 | * since this is a core component, and is essential for the | 1436 | * that allows fast recovery when the CPU comes back. |
1417 | * subsequent light-weight ->init() to succeed. | ||
1418 | */ | 1437 | */ |
1419 | if (cpufreq_driver->exit) { | 1438 | if (cpufreq_driver->offline) { |
1439 | cpufreq_driver->offline(policy); | ||
1440 | } else if (cpufreq_driver->exit) { | ||
1420 | cpufreq_driver->exit(policy); | 1441 | cpufreq_driver->exit(policy); |
1421 | policy->freq_table = NULL; | 1442 | policy->freq_table = NULL; |
1422 | } | 1443 | } |
@@ -1445,8 +1466,13 @@ static void cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) | |||
1445 | cpumask_clear_cpu(cpu, policy->real_cpus); | 1466 | cpumask_clear_cpu(cpu, policy->real_cpus); |
1446 | remove_cpu_dev_symlink(policy, dev); | 1467 | remove_cpu_dev_symlink(policy, dev); |
1447 | 1468 | ||
1448 | if (cpumask_empty(policy->real_cpus)) | 1469 | if (cpumask_empty(policy->real_cpus)) { |
1470 | /* We did light-weight exit earlier, do full tear down now */ | ||
1471 | if (cpufreq_driver->offline) | ||
1472 | cpufreq_driver->exit(policy); | ||
1473 | |||
1449 | cpufreq_policy_free(policy); | 1474 | cpufreq_policy_free(policy); |
1475 | } | ||
1450 | } | 1476 | } |
1451 | 1477 | ||
1452 | /** | 1478 | /** |
@@ -2192,12 +2218,25 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) | |||
2192 | } | 2218 | } |
2193 | EXPORT_SYMBOL(cpufreq_get_policy); | 2219 | EXPORT_SYMBOL(cpufreq_get_policy); |
2194 | 2220 | ||
2195 | /* | 2221 | /** |
2196 | * policy : current policy. | 2222 | * cpufreq_set_policy - Modify cpufreq policy parameters. |
2197 | * new_policy: policy to be set. | 2223 | * @policy: Policy object to modify. |
2224 | * @new_policy: New policy data. | ||
2225 | * | ||
2226 | * Pass @new_policy to the cpufreq driver's ->verify() callback, run the | ||
2227 | * installed policy notifiers for it with the CPUFREQ_ADJUST value, pass it to | ||
2228 | * the driver's ->verify() callback again and run the notifiers for it again | ||
2229 | * with the CPUFREQ_NOTIFY value. Next, copy the min and max parameters | ||
2230 | * of @new_policy to @policy and either invoke the driver's ->setpolicy() | ||
2231 | * callback (if present) or carry out a governor update for @policy. That is, | ||
2232 | * run the current governor's ->limits() callback (if the governor field in | ||
2233 | * @new_policy points to the same object as the one in @policy) or replace the | ||
2234 | * governor for @policy with the new one stored in @new_policy. | ||
2235 | * | ||
2236 | * The cpuinfo part of @policy is not updated by this function. | ||
2198 | */ | 2237 | */ |
2199 | static int cpufreq_set_policy(struct cpufreq_policy *policy, | 2238 | static int cpufreq_set_policy(struct cpufreq_policy *policy, |
2200 | struct cpufreq_policy *new_policy) | 2239 | struct cpufreq_policy *new_policy) |
2201 | { | 2240 | { |
2202 | struct cpufreq_governor *old_gov; | 2241 | struct cpufreq_governor *old_gov; |
2203 | int ret; | 2242 | int ret; |
@@ -2247,11 +2286,11 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, | |||
2247 | if (cpufreq_driver->setpolicy) { | 2286 | if (cpufreq_driver->setpolicy) { |
2248 | policy->policy = new_policy->policy; | 2287 | policy->policy = new_policy->policy; |
2249 | pr_debug("setting range\n"); | 2288 | pr_debug("setting range\n"); |
2250 | return cpufreq_driver->setpolicy(new_policy); | 2289 | return cpufreq_driver->setpolicy(policy); |
2251 | } | 2290 | } |
2252 | 2291 | ||
2253 | if (new_policy->governor == policy->governor) { | 2292 | if (new_policy->governor == policy->governor) { |
2254 | pr_debug("cpufreq: governor limits update\n"); | 2293 | pr_debug("governor limits update\n"); |
2255 | cpufreq_governor_limits(policy); | 2294 | cpufreq_governor_limits(policy); |
2256 | return 0; | 2295 | return 0; |
2257 | } | 2296 | } |
@@ -2272,7 +2311,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, | |||
2272 | if (!ret) { | 2311 | if (!ret) { |
2273 | ret = cpufreq_start_governor(policy); | 2312 | ret = cpufreq_start_governor(policy); |
2274 | if (!ret) { | 2313 | if (!ret) { |
2275 | pr_debug("cpufreq: governor change\n"); | 2314 | pr_debug("governor change\n"); |
2276 | sched_cpufreq_governor_change(policy, old_gov); | 2315 | sched_cpufreq_governor_change(policy, old_gov); |
2277 | return 0; | 2316 | return 0; |
2278 | } | 2317 | } |
@@ -2293,11 +2332,14 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy, | |||
2293 | } | 2332 | } |
2294 | 2333 | ||
2295 | /** | 2334 | /** |
2296 | * cpufreq_update_policy - re-evaluate an existing cpufreq policy | 2335 | * cpufreq_update_policy - Re-evaluate an existing cpufreq policy. |
2297 | * @cpu: CPU which shall be re-evaluated | 2336 | * @cpu: CPU to re-evaluate the policy for. |
2298 | * | 2337 | * |
2299 | * Useful for policy notifiers which have different necessities | 2338 | * Update the current frequency for the cpufreq policy of @cpu and use |
2300 | * at different times. | 2339 | * cpufreq_set_policy() to re-apply the min and max limits saved in the |
2340 | * user_policy sub-structure of that policy, which triggers the evaluation | ||
2341 | * of policy notifiers and the cpufreq driver's ->verify() callback for the | ||
2342 | * policy in question, among other things. | ||
2301 | */ | 2343 | */ |
2302 | void cpufreq_update_policy(unsigned int cpu) | 2344 | void cpufreq_update_policy(unsigned int cpu) |
2303 | { | 2345 | { |
@@ -2312,23 +2354,18 @@ void cpufreq_update_policy(unsigned int cpu) | |||
2312 | if (policy_is_inactive(policy)) | 2354 | if (policy_is_inactive(policy)) |
2313 | goto unlock; | 2355 | goto unlock; |
2314 | 2356 | ||
2315 | pr_debug("updating policy for CPU %u\n", cpu); | ||
2316 | memcpy(&new_policy, policy, sizeof(*policy)); | ||
2317 | new_policy.min = policy->user_policy.min; | ||
2318 | new_policy.max = policy->user_policy.max; | ||
2319 | |||
2320 | /* | 2357 | /* |
2321 | * BIOS might change freq behind our back | 2358 | * BIOS might change freq behind our back |
2322 | * -> ask driver for current freq and notify governors about a change | 2359 | * -> ask driver for current freq and notify governors about a change |
2323 | */ | 2360 | */ |
2324 | if (cpufreq_driver->get && !cpufreq_driver->setpolicy) { | 2361 | if (cpufreq_driver->get && !cpufreq_driver->setpolicy && |
2325 | if (cpufreq_suspended) | 2362 | (cpufreq_suspended || WARN_ON(!cpufreq_update_current_freq(policy)))) |
2326 | goto unlock; | 2363 | goto unlock; |
2327 | 2364 | ||
2328 | new_policy.cur = cpufreq_update_current_freq(policy); | 2365 | pr_debug("updating policy for CPU %u\n", cpu); |
2329 | if (WARN_ON(!new_policy.cur)) | 2366 | memcpy(&new_policy, policy, sizeof(*policy)); |
2330 | goto unlock; | 2367 | new_policy.min = policy->user_policy.min; |
2331 | } | 2368 | new_policy.max = policy->user_policy.max; |
2332 | 2369 | ||
2333 | cpufreq_set_policy(policy, &new_policy); | 2370 | cpufreq_set_policy(policy, &new_policy); |
2334 | 2371 | ||
@@ -2479,7 +2516,8 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) | |||
2479 | driver_data->target) || | 2516 | driver_data->target) || |
2480 | (driver_data->setpolicy && (driver_data->target_index || | 2517 | (driver_data->setpolicy && (driver_data->target_index || |
2481 | driver_data->target)) || | 2518 | driver_data->target)) || |
2482 | (!!driver_data->get_intermediate != !!driver_data->target_intermediate)) | 2519 | (!driver_data->get_intermediate != !driver_data->target_intermediate) || |
2520 | (!driver_data->online != !driver_data->offline)) | ||
2483 | return -EINVAL; | 2521 | return -EINVAL; |
2484 | 2522 | ||
2485 | pr_debug("trying to register driver %s\n", driver_data->name); | 2523 | pr_debug("trying to register driver %s\n", driver_data->name); |
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 1572129844a5..e2db5581489a 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -31,26 +31,27 @@ static void cpufreq_stats_update(struct cpufreq_stats *stats) | |||
31 | { | 31 | { |
32 | unsigned long long cur_time = get_jiffies_64(); | 32 | unsigned long long cur_time = get_jiffies_64(); |
33 | 33 | ||
34 | spin_lock(&cpufreq_stats_lock); | ||
35 | stats->time_in_state[stats->last_index] += cur_time - stats->last_time; | 34 | stats->time_in_state[stats->last_index] += cur_time - stats->last_time; |
36 | stats->last_time = cur_time; | 35 | stats->last_time = cur_time; |
37 | spin_unlock(&cpufreq_stats_lock); | ||
38 | } | 36 | } |
39 | 37 | ||
40 | static void cpufreq_stats_clear_table(struct cpufreq_stats *stats) | 38 | static void cpufreq_stats_clear_table(struct cpufreq_stats *stats) |
41 | { | 39 | { |
42 | unsigned int count = stats->max_state; | 40 | unsigned int count = stats->max_state; |
43 | 41 | ||
42 | spin_lock(&cpufreq_stats_lock); | ||
44 | memset(stats->time_in_state, 0, count * sizeof(u64)); | 43 | memset(stats->time_in_state, 0, count * sizeof(u64)); |
45 | memset(stats->trans_table, 0, count * count * sizeof(int)); | 44 | memset(stats->trans_table, 0, count * count * sizeof(int)); |
46 | stats->last_time = get_jiffies_64(); | 45 | stats->last_time = get_jiffies_64(); |
47 | stats->total_trans = 0; | 46 | stats->total_trans = 0; |
47 | spin_unlock(&cpufreq_stats_lock); | ||
48 | } | 48 | } |
49 | 49 | ||
50 | static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) | 50 | static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) |
51 | { | 51 | { |
52 | return sprintf(buf, "%d\n", policy->stats->total_trans); | 52 | return sprintf(buf, "%d\n", policy->stats->total_trans); |
53 | } | 53 | } |
54 | cpufreq_freq_attr_ro(total_trans); | ||
54 | 55 | ||
55 | static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) | 56 | static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) |
56 | { | 57 | { |
@@ -61,7 +62,10 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) | |||
61 | if (policy->fast_switch_enabled) | 62 | if (policy->fast_switch_enabled) |
62 | return 0; | 63 | return 0; |
63 | 64 | ||
65 | spin_lock(&cpufreq_stats_lock); | ||
64 | cpufreq_stats_update(stats); | 66 | cpufreq_stats_update(stats); |
67 | spin_unlock(&cpufreq_stats_lock); | ||
68 | |||
65 | for (i = 0; i < stats->state_num; i++) { | 69 | for (i = 0; i < stats->state_num; i++) { |
66 | len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], | 70 | len += sprintf(buf + len, "%u %llu\n", stats->freq_table[i], |
67 | (unsigned long long) | 71 | (unsigned long long) |
@@ -69,6 +73,7 @@ static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) | |||
69 | } | 73 | } |
70 | return len; | 74 | return len; |
71 | } | 75 | } |
76 | cpufreq_freq_attr_ro(time_in_state); | ||
72 | 77 | ||
73 | static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf, | 78 | static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf, |
74 | size_t count) | 79 | size_t count) |
@@ -77,6 +82,7 @@ static ssize_t store_reset(struct cpufreq_policy *policy, const char *buf, | |||
77 | cpufreq_stats_clear_table(policy->stats); | 82 | cpufreq_stats_clear_table(policy->stats); |
78 | return count; | 83 | return count; |
79 | } | 84 | } |
85 | cpufreq_freq_attr_wo(reset); | ||
80 | 86 | ||
81 | static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) | 87 | static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) |
82 | { | 88 | { |
@@ -126,10 +132,6 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) | |||
126 | } | 132 | } |
127 | cpufreq_freq_attr_ro(trans_table); | 133 | cpufreq_freq_attr_ro(trans_table); |
128 | 134 | ||
129 | cpufreq_freq_attr_ro(total_trans); | ||
130 | cpufreq_freq_attr_ro(time_in_state); | ||
131 | cpufreq_freq_attr_wo(reset); | ||
132 | |||
133 | static struct attribute *default_attrs[] = { | 135 | static struct attribute *default_attrs[] = { |
134 | &total_trans.attr, | 136 | &total_trans.attr, |
135 | &time_in_state.attr, | 137 | &time_in_state.attr, |
@@ -240,9 +242,11 @@ void cpufreq_stats_record_transition(struct cpufreq_policy *policy, | |||
240 | if (old_index == -1 || new_index == -1 || old_index == new_index) | 242 | if (old_index == -1 || new_index == -1 || old_index == new_index) |
241 | return; | 243 | return; |
242 | 244 | ||
245 | spin_lock(&cpufreq_stats_lock); | ||
243 | cpufreq_stats_update(stats); | 246 | cpufreq_stats_update(stats); |
244 | 247 | ||
245 | stats->last_index = new_index; | 248 | stats->last_index = new_index; |
246 | stats->trans_table[old_index * stats->max_state + new_index]++; | 249 | stats->trans_table[old_index * stats->max_state + new_index]++; |
247 | stats->total_trans++; | 250 | stats->total_trans++; |
251 | spin_unlock(&cpufreq_stats_lock); | ||
248 | } | 252 | } |
diff --git a/drivers/cpufreq/davinci-cpufreq.c b/drivers/cpufreq/davinci-cpufreq.c index d54a27c99121..940fe85db97a 100644 --- a/drivers/cpufreq/davinci-cpufreq.c +++ b/drivers/cpufreq/davinci-cpufreq.c | |||
@@ -23,13 +23,10 @@ | |||
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/clk.h> | 25 | #include <linux/clk.h> |
26 | #include <linux/platform_data/davinci-cpufreq.h> | ||
26 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
27 | #include <linux/export.h> | 28 | #include <linux/export.h> |
28 | 29 | ||
29 | #include <mach/hardware.h> | ||
30 | #include <mach/cpufreq.h> | ||
31 | #include <mach/common.h> | ||
32 | |||
33 | struct davinci_cpufreq { | 30 | struct davinci_cpufreq { |
34 | struct device *dev; | 31 | struct device *dev; |
35 | struct clk *armclk; | 32 | struct clk *armclk; |
diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index 60bea302abbe..2d3ef208dd70 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c | |||
@@ -323,9 +323,8 @@ static int eps_cpu_init(struct cpufreq_policy *policy) | |||
323 | states = 2; | 323 | states = 2; |
324 | 324 | ||
325 | /* Allocate private data and frequency table for current cpu */ | 325 | /* Allocate private data and frequency table for current cpu */ |
326 | centaur = kzalloc(sizeof(*centaur) | 326 | centaur = kzalloc(struct_size(centaur, freq_table, states + 1), |
327 | + (states + 1) * sizeof(struct cpufreq_frequency_table), | 327 | GFP_KERNEL); |
328 | GFP_KERNEL); | ||
329 | if (!centaur) | 328 | if (!centaur) |
330 | return -ENOMEM; | 329 | return -ENOMEM; |
331 | eps_cpu[0] = centaur; | 330 | eps_cpu[0] = centaur; |
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 9fedf627e000..ca955713e070 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <linux/clk.h> | 9 | #include <linux/clk.h> |
10 | #include <linux/cpu.h> | 10 | #include <linux/cpu.h> |
11 | #include <linux/cpufreq.h> | 11 | #include <linux/cpufreq.h> |
12 | #include <linux/cpu_cooling.h> | ||
13 | #include <linux/err.h> | 12 | #include <linux/err.h> |
14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
15 | #include <linux/nvmem-consumer.h> | 14 | #include <linux/nvmem-consumer.h> |
@@ -52,7 +51,6 @@ static struct clk_bulk_data clks[] = { | |||
52 | }; | 51 | }; |
53 | 52 | ||
54 | static struct device *cpu_dev; | 53 | static struct device *cpu_dev; |
55 | static struct thermal_cooling_device *cdev; | ||
56 | static bool free_opp; | 54 | static bool free_opp; |
57 | static struct cpufreq_frequency_table *freq_table; | 55 | static struct cpufreq_frequency_table *freq_table; |
58 | static unsigned int max_freq; | 56 | static unsigned int max_freq; |
@@ -193,16 +191,6 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index) | |||
193 | return 0; | 191 | return 0; |
194 | } | 192 | } |
195 | 193 | ||
196 | static void imx6q_cpufreq_ready(struct cpufreq_policy *policy) | ||
197 | { | ||
198 | cdev = of_cpufreq_cooling_register(policy); | ||
199 | |||
200 | if (!cdev) | ||
201 | dev_err(cpu_dev, | ||
202 | "running cpufreq without cooling device: %ld\n", | ||
203 | PTR_ERR(cdev)); | ||
204 | } | ||
205 | |||
206 | static int imx6q_cpufreq_init(struct cpufreq_policy *policy) | 194 | static int imx6q_cpufreq_init(struct cpufreq_policy *policy) |
207 | { | 195 | { |
208 | int ret; | 196 | int ret; |
@@ -214,22 +202,14 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy) | |||
214 | return ret; | 202 | return ret; |
215 | } | 203 | } |
216 | 204 | ||
217 | static int imx6q_cpufreq_exit(struct cpufreq_policy *policy) | ||
218 | { | ||
219 | cpufreq_cooling_unregister(cdev); | ||
220 | |||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static struct cpufreq_driver imx6q_cpufreq_driver = { | 205 | static struct cpufreq_driver imx6q_cpufreq_driver = { |
225 | .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, | 206 | .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
207 | CPUFREQ_IS_COOLING_DEV, | ||
226 | .verify = cpufreq_generic_frequency_table_verify, | 208 | .verify = cpufreq_generic_frequency_table_verify, |
227 | .target_index = imx6q_set_target, | 209 | .target_index = imx6q_set_target, |
228 | .get = cpufreq_generic_get, | 210 | .get = cpufreq_generic_get, |
229 | .init = imx6q_cpufreq_init, | 211 | .init = imx6q_cpufreq_init, |
230 | .exit = imx6q_cpufreq_exit, | ||
231 | .name = "imx6q-cpufreq", | 212 | .name = "imx6q-cpufreq", |
232 | .ready = imx6q_cpufreq_ready, | ||
233 | .attr = cpufreq_generic_attr, | 213 | .attr = cpufreq_generic_attr, |
234 | .suspend = cpufreq_generic_suspend, | 214 | .suspend = cpufreq_generic_suspend, |
235 | }; | 215 | }; |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index dd66decf2087..002f5169d4eb 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -50,6 +50,8 @@ | |||
50 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) | 50 | #define int_tofp(X) ((int64_t)(X) << FRAC_BITS) |
51 | #define fp_toint(X) ((X) >> FRAC_BITS) | 51 | #define fp_toint(X) ((X) >> FRAC_BITS) |
52 | 52 | ||
53 | #define ONE_EIGHTH_FP ((int64_t)1 << (FRAC_BITS - 3)) | ||
54 | |||
53 | #define EXT_BITS 6 | 55 | #define EXT_BITS 6 |
54 | #define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS) | 56 | #define EXT_FRAC_BITS (EXT_BITS + FRAC_BITS) |
55 | #define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS) | 57 | #define fp_ext_toint(X) ((X) >> EXT_FRAC_BITS) |
@@ -895,7 +897,7 @@ static void intel_pstate_update_policies(void) | |||
895 | /************************** sysfs begin ************************/ | 897 | /************************** sysfs begin ************************/ |
896 | #define show_one(file_name, object) \ | 898 | #define show_one(file_name, object) \ |
897 | static ssize_t show_##file_name \ | 899 | static ssize_t show_##file_name \ |
898 | (struct kobject *kobj, struct attribute *attr, char *buf) \ | 900 | (struct kobject *kobj, struct kobj_attribute *attr, char *buf) \ |
899 | { \ | 901 | { \ |
900 | return sprintf(buf, "%u\n", global.object); \ | 902 | return sprintf(buf, "%u\n", global.object); \ |
901 | } | 903 | } |
@@ -904,7 +906,7 @@ static ssize_t intel_pstate_show_status(char *buf); | |||
904 | static int intel_pstate_update_status(const char *buf, size_t size); | 906 | static int intel_pstate_update_status(const char *buf, size_t size); |
905 | 907 | ||
906 | static ssize_t show_status(struct kobject *kobj, | 908 | static ssize_t show_status(struct kobject *kobj, |
907 | struct attribute *attr, char *buf) | 909 | struct kobj_attribute *attr, char *buf) |
908 | { | 910 | { |
909 | ssize_t ret; | 911 | ssize_t ret; |
910 | 912 | ||
@@ -915,7 +917,7 @@ static ssize_t show_status(struct kobject *kobj, | |||
915 | return ret; | 917 | return ret; |
916 | } | 918 | } |
917 | 919 | ||
918 | static ssize_t store_status(struct kobject *a, struct attribute *b, | 920 | static ssize_t store_status(struct kobject *a, struct kobj_attribute *b, |
919 | const char *buf, size_t count) | 921 | const char *buf, size_t count) |
920 | { | 922 | { |
921 | char *p = memchr(buf, '\n', count); | 923 | char *p = memchr(buf, '\n', count); |
@@ -929,7 +931,7 @@ static ssize_t store_status(struct kobject *a, struct attribute *b, | |||
929 | } | 931 | } |
930 | 932 | ||
931 | static ssize_t show_turbo_pct(struct kobject *kobj, | 933 | static ssize_t show_turbo_pct(struct kobject *kobj, |
932 | struct attribute *attr, char *buf) | 934 | struct kobj_attribute *attr, char *buf) |
933 | { | 935 | { |
934 | struct cpudata *cpu; | 936 | struct cpudata *cpu; |
935 | int total, no_turbo, turbo_pct; | 937 | int total, no_turbo, turbo_pct; |
@@ -955,7 +957,7 @@ static ssize_t show_turbo_pct(struct kobject *kobj, | |||
955 | } | 957 | } |
956 | 958 | ||
957 | static ssize_t show_num_pstates(struct kobject *kobj, | 959 | static ssize_t show_num_pstates(struct kobject *kobj, |
958 | struct attribute *attr, char *buf) | 960 | struct kobj_attribute *attr, char *buf) |
959 | { | 961 | { |
960 | struct cpudata *cpu; | 962 | struct cpudata *cpu; |
961 | int total; | 963 | int total; |
@@ -976,7 +978,7 @@ static ssize_t show_num_pstates(struct kobject *kobj, | |||
976 | } | 978 | } |
977 | 979 | ||
978 | static ssize_t show_no_turbo(struct kobject *kobj, | 980 | static ssize_t show_no_turbo(struct kobject *kobj, |
979 | struct attribute *attr, char *buf) | 981 | struct kobj_attribute *attr, char *buf) |
980 | { | 982 | { |
981 | ssize_t ret; | 983 | ssize_t ret; |
982 | 984 | ||
@@ -998,7 +1000,7 @@ static ssize_t show_no_turbo(struct kobject *kobj, | |||
998 | return ret; | 1000 | return ret; |
999 | } | 1001 | } |
1000 | 1002 | ||
1001 | static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | 1003 | static ssize_t store_no_turbo(struct kobject *a, struct kobj_attribute *b, |
1002 | const char *buf, size_t count) | 1004 | const char *buf, size_t count) |
1003 | { | 1005 | { |
1004 | unsigned int input; | 1006 | unsigned int input; |
@@ -1045,7 +1047,7 @@ static ssize_t store_no_turbo(struct kobject *a, struct attribute *b, | |||
1045 | return count; | 1047 | return count; |
1046 | } | 1048 | } |
1047 | 1049 | ||
1048 | static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, | 1050 | static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, |
1049 | const char *buf, size_t count) | 1051 | const char *buf, size_t count) |
1050 | { | 1052 | { |
1051 | unsigned int input; | 1053 | unsigned int input; |
@@ -1075,7 +1077,7 @@ static ssize_t store_max_perf_pct(struct kobject *a, struct attribute *b, | |||
1075 | return count; | 1077 | return count; |
1076 | } | 1078 | } |
1077 | 1079 | ||
1078 | static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | 1080 | static ssize_t store_min_perf_pct(struct kobject *a, struct kobj_attribute *b, |
1079 | const char *buf, size_t count) | 1081 | const char *buf, size_t count) |
1080 | { | 1082 | { |
1081 | unsigned int input; | 1083 | unsigned int input; |
@@ -1107,12 +1109,13 @@ static ssize_t store_min_perf_pct(struct kobject *a, struct attribute *b, | |||
1107 | } | 1109 | } |
1108 | 1110 | ||
1109 | static ssize_t show_hwp_dynamic_boost(struct kobject *kobj, | 1111 | static ssize_t show_hwp_dynamic_boost(struct kobject *kobj, |
1110 | struct attribute *attr, char *buf) | 1112 | struct kobj_attribute *attr, char *buf) |
1111 | { | 1113 | { |
1112 | return sprintf(buf, "%u\n", hwp_boost); | 1114 | return sprintf(buf, "%u\n", hwp_boost); |
1113 | } | 1115 | } |
1114 | 1116 | ||
1115 | static ssize_t store_hwp_dynamic_boost(struct kobject *a, struct attribute *b, | 1117 | static ssize_t store_hwp_dynamic_boost(struct kobject *a, |
1118 | struct kobj_attribute *b, | ||
1116 | const char *buf, size_t count) | 1119 | const char *buf, size_t count) |
1117 | { | 1120 | { |
1118 | unsigned int input; | 1121 | unsigned int input; |
@@ -1444,12 +1447,6 @@ static int knl_get_turbo_pstate(void) | |||
1444 | return ret; | 1447 | return ret; |
1445 | } | 1448 | } |
1446 | 1449 | ||
1447 | static int intel_pstate_get_base_pstate(struct cpudata *cpu) | ||
1448 | { | ||
1449 | return global.no_turbo || global.turbo_disabled ? | ||
1450 | cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; | ||
1451 | } | ||
1452 | |||
1453 | static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) | 1450 | static void intel_pstate_set_pstate(struct cpudata *cpu, int pstate) |
1454 | { | 1451 | { |
1455 | trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); | 1452 | trace_cpu_frequency(pstate * cpu->pstate.scaling, cpu->cpu); |
@@ -1470,11 +1467,9 @@ static void intel_pstate_set_min_pstate(struct cpudata *cpu) | |||
1470 | 1467 | ||
1471 | static void intel_pstate_max_within_limits(struct cpudata *cpu) | 1468 | static void intel_pstate_max_within_limits(struct cpudata *cpu) |
1472 | { | 1469 | { |
1473 | int pstate; | 1470 | int pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio); |
1474 | 1471 | ||
1475 | update_turbo_state(); | 1472 | update_turbo_state(); |
1476 | pstate = intel_pstate_get_base_pstate(cpu); | ||
1477 | pstate = max(cpu->pstate.min_pstate, cpu->max_perf_ratio); | ||
1478 | intel_pstate_set_pstate(cpu, pstate); | 1473 | intel_pstate_set_pstate(cpu, pstate); |
1479 | } | 1474 | } |
1480 | 1475 | ||
@@ -1678,17 +1673,14 @@ static inline int32_t get_avg_pstate(struct cpudata *cpu) | |||
1678 | static inline int32_t get_target_pstate(struct cpudata *cpu) | 1673 | static inline int32_t get_target_pstate(struct cpudata *cpu) |
1679 | { | 1674 | { |
1680 | struct sample *sample = &cpu->sample; | 1675 | struct sample *sample = &cpu->sample; |
1681 | int32_t busy_frac, boost; | 1676 | int32_t busy_frac; |
1682 | int target, avg_pstate; | 1677 | int target, avg_pstate; |
1683 | 1678 | ||
1684 | busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift, | 1679 | busy_frac = div_fp(sample->mperf << cpu->aperf_mperf_shift, |
1685 | sample->tsc); | 1680 | sample->tsc); |
1686 | 1681 | ||
1687 | boost = cpu->iowait_boost; | 1682 | if (busy_frac < cpu->iowait_boost) |
1688 | cpu->iowait_boost >>= 1; | 1683 | busy_frac = cpu->iowait_boost; |
1689 | |||
1690 | if (busy_frac < boost) | ||
1691 | busy_frac = boost; | ||
1692 | 1684 | ||
1693 | sample->busy_scaled = busy_frac * 100; | 1685 | sample->busy_scaled = busy_frac * 100; |
1694 | 1686 | ||
@@ -1715,11 +1707,9 @@ static inline int32_t get_target_pstate(struct cpudata *cpu) | |||
1715 | 1707 | ||
1716 | static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate) | 1708 | static int intel_pstate_prepare_request(struct cpudata *cpu, int pstate) |
1717 | { | 1709 | { |
1718 | int max_pstate = intel_pstate_get_base_pstate(cpu); | 1710 | int min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio); |
1719 | int min_pstate; | 1711 | int max_pstate = max(min_pstate, cpu->max_perf_ratio); |
1720 | 1712 | ||
1721 | min_pstate = max(cpu->pstate.min_pstate, cpu->min_perf_ratio); | ||
1722 | max_pstate = max(min_pstate, cpu->max_perf_ratio); | ||
1723 | return clamp_t(int, pstate, min_pstate, max_pstate); | 1713 | return clamp_t(int, pstate, min_pstate, max_pstate); |
1724 | } | 1714 | } |
1725 | 1715 | ||
@@ -1767,29 +1757,30 @@ static void intel_pstate_update_util(struct update_util_data *data, u64 time, | |||
1767 | if (smp_processor_id() != cpu->cpu) | 1757 | if (smp_processor_id() != cpu->cpu) |
1768 | return; | 1758 | return; |
1769 | 1759 | ||
1760 | delta_ns = time - cpu->last_update; | ||
1770 | if (flags & SCHED_CPUFREQ_IOWAIT) { | 1761 | if (flags & SCHED_CPUFREQ_IOWAIT) { |
1771 | cpu->iowait_boost = int_tofp(1); | 1762 | /* Start over if the CPU may have been idle. */ |
1772 | cpu->last_update = time; | 1763 | if (delta_ns > TICK_NSEC) { |
1773 | /* | 1764 | cpu->iowait_boost = ONE_EIGHTH_FP; |
1774 | * The last time the busy was 100% so P-state was max anyway | 1765 | } else if (cpu->iowait_boost) { |
1775 | * so avoid overhead of computation. | 1766 | cpu->iowait_boost <<= 1; |
1776 | */ | 1767 | if (cpu->iowait_boost > int_tofp(1)) |
1777 | if (fp_toint(cpu->sample.busy_scaled) == 100) | 1768 | cpu->iowait_boost = int_tofp(1); |
1778 | return; | 1769 | } else { |
1779 | 1770 | cpu->iowait_boost = ONE_EIGHTH_FP; | |
1780 | goto set_pstate; | 1771 | } |
1781 | } else if (cpu->iowait_boost) { | 1772 | } else if (cpu->iowait_boost) { |
1782 | /* Clear iowait_boost if the CPU may have been idle. */ | 1773 | /* Clear iowait_boost if the CPU may have been idle. */ |
1783 | delta_ns = time - cpu->last_update; | ||
1784 | if (delta_ns > TICK_NSEC) | 1774 | if (delta_ns > TICK_NSEC) |
1785 | cpu->iowait_boost = 0; | 1775 | cpu->iowait_boost = 0; |
1776 | else | ||
1777 | cpu->iowait_boost >>= 1; | ||
1786 | } | 1778 | } |
1787 | cpu->last_update = time; | 1779 | cpu->last_update = time; |
1788 | delta_ns = time - cpu->sample.time; | 1780 | delta_ns = time - cpu->sample.time; |
1789 | if ((s64)delta_ns < INTEL_PSTATE_SAMPLING_INTERVAL) | 1781 | if ((s64)delta_ns < INTEL_PSTATE_SAMPLING_INTERVAL) |
1790 | return; | 1782 | return; |
1791 | 1783 | ||
1792 | set_pstate: | ||
1793 | if (intel_pstate_sample(cpu, time)) | 1784 | if (intel_pstate_sample(cpu, time)) |
1794 | intel_pstate_adjust_pstate(cpu); | 1785 | intel_pstate_adjust_pstate(cpu); |
1795 | } | 1786 | } |
@@ -1976,7 +1967,8 @@ static void intel_pstate_update_perf_limits(struct cpufreq_policy *policy, | |||
1976 | if (hwp_active) { | 1967 | if (hwp_active) { |
1977 | intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state); | 1968 | intel_pstate_get_hwp_max(cpu->cpu, &turbo_max, &max_state); |
1978 | } else { | 1969 | } else { |
1979 | max_state = intel_pstate_get_base_pstate(cpu); | 1970 | max_state = global.no_turbo || global.turbo_disabled ? |
1971 | cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; | ||
1980 | turbo_max = cpu->pstate.turbo_pstate; | 1972 | turbo_max = cpu->pstate.turbo_pstate; |
1981 | } | 1973 | } |
1982 | 1974 | ||
@@ -2475,6 +2467,7 @@ static bool __init intel_pstate_no_acpi_pss(void) | |||
2475 | kfree(pss); | 2467 | kfree(pss); |
2476 | } | 2468 | } |
2477 | 2469 | ||
2470 | pr_debug("ACPI _PSS not found\n"); | ||
2478 | return true; | 2471 | return true; |
2479 | } | 2472 | } |
2480 | 2473 | ||
@@ -2485,9 +2478,14 @@ static bool __init intel_pstate_no_acpi_pcch(void) | |||
2485 | 2478 | ||
2486 | status = acpi_get_handle(NULL, "\\_SB", &handle); | 2479 | status = acpi_get_handle(NULL, "\\_SB", &handle); |
2487 | if (ACPI_FAILURE(status)) | 2480 | if (ACPI_FAILURE(status)) |
2488 | return true; | 2481 | goto not_found; |
2482 | |||
2483 | if (acpi_has_method(handle, "PCCH")) | ||
2484 | return false; | ||
2489 | 2485 | ||
2490 | return !acpi_has_method(handle, "PCCH"); | 2486 | not_found: |
2487 | pr_debug("ACPI PCCH not found\n"); | ||
2488 | return true; | ||
2491 | } | 2489 | } |
2492 | 2490 | ||
2493 | static bool __init intel_pstate_has_acpi_ppc(void) | 2491 | static bool __init intel_pstate_has_acpi_ppc(void) |
@@ -2502,6 +2500,7 @@ static bool __init intel_pstate_has_acpi_ppc(void) | |||
2502 | if (acpi_has_method(pr->handle, "_PPC")) | 2500 | if (acpi_has_method(pr->handle, "_PPC")) |
2503 | return true; | 2501 | return true; |
2504 | } | 2502 | } |
2503 | pr_debug("ACPI _PPC not found\n"); | ||
2505 | return false; | 2504 | return false; |
2506 | } | 2505 | } |
2507 | 2506 | ||
@@ -2539,8 +2538,10 @@ static bool __init intel_pstate_platform_pwr_mgmt_exists(void) | |||
2539 | id = x86_match_cpu(intel_pstate_cpu_oob_ids); | 2538 | id = x86_match_cpu(intel_pstate_cpu_oob_ids); |
2540 | if (id) { | 2539 | if (id) { |
2541 | rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr); | 2540 | rdmsrl(MSR_MISC_PWR_MGMT, misc_pwr); |
2542 | if ( misc_pwr & (1 << 8)) | 2541 | if (misc_pwr & (1 << 8)) { |
2542 | pr_debug("Bit 8 in the MISC_PWR_MGMT MSR set\n"); | ||
2543 | return true; | 2543 | return true; |
2544 | } | ||
2544 | } | 2545 | } |
2545 | 2546 | ||
2546 | idx = acpi_match_platform_list(plat_info); | 2547 | idx = acpi_match_platform_list(plat_info); |
@@ -2606,22 +2607,28 @@ static int __init intel_pstate_init(void) | |||
2606 | } | 2607 | } |
2607 | } else { | 2608 | } else { |
2608 | id = x86_match_cpu(intel_pstate_cpu_ids); | 2609 | id = x86_match_cpu(intel_pstate_cpu_ids); |
2609 | if (!id) | 2610 | if (!id) { |
2611 | pr_info("CPU ID not supported\n"); | ||
2610 | return -ENODEV; | 2612 | return -ENODEV; |
2613 | } | ||
2611 | 2614 | ||
2612 | copy_cpu_funcs((struct pstate_funcs *)id->driver_data); | 2615 | copy_cpu_funcs((struct pstate_funcs *)id->driver_data); |
2613 | } | 2616 | } |
2614 | 2617 | ||
2615 | if (intel_pstate_msrs_not_valid()) | 2618 | if (intel_pstate_msrs_not_valid()) { |
2619 | pr_info("Invalid MSRs\n"); | ||
2616 | return -ENODEV; | 2620 | return -ENODEV; |
2621 | } | ||
2617 | 2622 | ||
2618 | hwp_cpu_matched: | 2623 | hwp_cpu_matched: |
2619 | /* | 2624 | /* |
2620 | * The Intel pstate driver will be ignored if the platform | 2625 | * The Intel pstate driver will be ignored if the platform |
2621 | * firmware has its own power management modes. | 2626 | * firmware has its own power management modes. |
2622 | */ | 2627 | */ |
2623 | if (intel_pstate_platform_pwr_mgmt_exists()) | 2628 | if (intel_pstate_platform_pwr_mgmt_exists()) { |
2629 | pr_info("P-states controlled by the platform\n"); | ||
2624 | return -ENODEV; | 2630 | return -ENODEV; |
2631 | } | ||
2625 | 2632 | ||
2626 | if (!hwp_active && hwp_only) | 2633 | if (!hwp_active && hwp_only) |
2627 | return -ENOTSUPP; | 2634 | return -ENOTSUPP; |
diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 279bd9e9fa95..fb546e0d0356 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c | |||
@@ -851,7 +851,7 @@ static int longhaul_cpu_init(struct cpufreq_policy *policy) | |||
851 | case TYPE_POWERSAVER: | 851 | case TYPE_POWERSAVER: |
852 | pr_cont("Powersaver supported\n"); | 852 | pr_cont("Powersaver supported\n"); |
853 | break; | 853 | break; |
854 | }; | 854 | } |
855 | 855 | ||
856 | /* Doesn't hurt */ | 856 | /* Doesn't hurt */ |
857 | longhaul_setup_southbridge(); | 857 | longhaul_setup_southbridge(); |
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c index eb8920d39818..4229fcc31310 100644 --- a/drivers/cpufreq/mediatek-cpufreq.c +++ b/drivers/cpufreq/mediatek-cpufreq.c | |||
@@ -14,7 +14,6 @@ | |||
14 | 14 | ||
15 | #include <linux/clk.h> | 15 | #include <linux/clk.h> |
16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
17 | #include <linux/cpu_cooling.h> | ||
18 | #include <linux/cpufreq.h> | 17 | #include <linux/cpufreq.h> |
19 | #include <linux/cpumask.h> | 18 | #include <linux/cpumask.h> |
20 | #include <linux/module.h> | 19 | #include <linux/module.h> |
@@ -48,7 +47,6 @@ struct mtk_cpu_dvfs_info { | |||
48 | struct regulator *sram_reg; | 47 | struct regulator *sram_reg; |
49 | struct clk *cpu_clk; | 48 | struct clk *cpu_clk; |
50 | struct clk *inter_clk; | 49 | struct clk *inter_clk; |
51 | struct thermal_cooling_device *cdev; | ||
52 | struct list_head list_head; | 50 | struct list_head list_head; |
53 | int intermediate_voltage; | 51 | int intermediate_voltage; |
54 | bool need_voltage_tracking; | 52 | bool need_voltage_tracking; |
@@ -307,13 +305,6 @@ static int mtk_cpufreq_set_target(struct cpufreq_policy *policy, | |||
307 | 305 | ||
308 | #define DYNAMIC_POWER "dynamic-power-coefficient" | 306 | #define DYNAMIC_POWER "dynamic-power-coefficient" |
309 | 307 | ||
310 | static void mtk_cpufreq_ready(struct cpufreq_policy *policy) | ||
311 | { | ||
312 | struct mtk_cpu_dvfs_info *info = policy->driver_data; | ||
313 | |||
314 | info->cdev = of_cpufreq_cooling_register(policy); | ||
315 | } | ||
316 | |||
317 | static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) | 308 | static int mtk_cpu_dvfs_info_init(struct mtk_cpu_dvfs_info *info, int cpu) |
318 | { | 309 | { |
319 | struct device *cpu_dev; | 310 | struct device *cpu_dev; |
@@ -472,7 +463,6 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy) | |||
472 | { | 463 | { |
473 | struct mtk_cpu_dvfs_info *info = policy->driver_data; | 464 | struct mtk_cpu_dvfs_info *info = policy->driver_data; |
474 | 465 | ||
475 | cpufreq_cooling_unregister(info->cdev); | ||
476 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); | 466 | dev_pm_opp_free_cpufreq_table(info->cpu_dev, &policy->freq_table); |
477 | 467 | ||
478 | return 0; | 468 | return 0; |
@@ -480,13 +470,13 @@ static int mtk_cpufreq_exit(struct cpufreq_policy *policy) | |||
480 | 470 | ||
481 | static struct cpufreq_driver mtk_cpufreq_driver = { | 471 | static struct cpufreq_driver mtk_cpufreq_driver = { |
482 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | | 472 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
483 | CPUFREQ_HAVE_GOVERNOR_PER_POLICY, | 473 | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | |
474 | CPUFREQ_IS_COOLING_DEV, | ||
484 | .verify = cpufreq_generic_frequency_table_verify, | 475 | .verify = cpufreq_generic_frequency_table_verify, |
485 | .target_index = mtk_cpufreq_set_target, | 476 | .target_index = mtk_cpufreq_set_target, |
486 | .get = cpufreq_generic_get, | 477 | .get = cpufreq_generic_get, |
487 | .init = mtk_cpufreq_init, | 478 | .init = mtk_cpufreq_init, |
488 | .exit = mtk_cpufreq_exit, | 479 | .exit = mtk_cpufreq_exit, |
489 | .ready = mtk_cpufreq_ready, | ||
490 | .name = "mtk-cpufreq", | 480 | .name = "mtk-cpufreq", |
491 | .attr = cpufreq_generic_attr, | 481 | .attr = cpufreq_generic_attr, |
492 | }; | 482 | }; |
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 099a849396f6..1e5e64643c3a 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c | |||
@@ -268,7 +268,7 @@ static int pcc_get_offset(int cpu) | |||
268 | if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) { | 268 | if (!pccp || pccp->type != ACPI_TYPE_PACKAGE) { |
269 | ret = -ENODEV; | 269 | ret = -ENODEV; |
270 | goto out_free; | 270 | goto out_free; |
271 | }; | 271 | } |
272 | 272 | ||
273 | offset = &(pccp->package.elements[0]); | 273 | offset = &(pccp->package.elements[0]); |
274 | if (!offset || offset->type != ACPI_TYPE_INTEGER) { | 274 | if (!offset || offset->type != ACPI_TYPE_INTEGER) { |
diff --git a/drivers/cpufreq/powernv-cpufreq.c b/drivers/cpufreq/powernv-cpufreq.c index 7e7ad3879c4e..d2230812fa4b 100644 --- a/drivers/cpufreq/powernv-cpufreq.c +++ b/drivers/cpufreq/powernv-cpufreq.c | |||
@@ -244,6 +244,7 @@ static int init_powernv_pstates(void) | |||
244 | u32 len_ids, len_freqs; | 244 | u32 len_ids, len_freqs; |
245 | u32 pstate_min, pstate_max, pstate_nominal; | 245 | u32 pstate_min, pstate_max, pstate_nominal; |
246 | u32 pstate_turbo, pstate_ultra_turbo; | 246 | u32 pstate_turbo, pstate_ultra_turbo; |
247 | int rc = -ENODEV; | ||
247 | 248 | ||
248 | power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); | 249 | power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); |
249 | if (!power_mgt) { | 250 | if (!power_mgt) { |
@@ -327,8 +328,11 @@ next: | |||
327 | powernv_freqs[i].frequency = freq * 1000; /* kHz */ | 328 | powernv_freqs[i].frequency = freq * 1000; /* kHz */ |
328 | powernv_freqs[i].driver_data = id & 0xFF; | 329 | powernv_freqs[i].driver_data = id & 0xFF; |
329 | 330 | ||
330 | revmap_data = (struct pstate_idx_revmap_data *) | 331 | revmap_data = kmalloc(sizeof(*revmap_data), GFP_KERNEL); |
331 | kmalloc(sizeof(*revmap_data), GFP_KERNEL); | 332 | if (!revmap_data) { |
333 | rc = -ENOMEM; | ||
334 | goto out; | ||
335 | } | ||
332 | 336 | ||
333 | revmap_data->pstate_id = id & 0xFF; | 337 | revmap_data->pstate_id = id & 0xFF; |
334 | revmap_data->cpufreq_table_idx = i; | 338 | revmap_data->cpufreq_table_idx = i; |
@@ -357,7 +361,7 @@ next: | |||
357 | return 0; | 361 | return 0; |
358 | out: | 362 | out: |
359 | of_node_put(power_mgt); | 363 | of_node_put(power_mgt); |
360 | return -ENODEV; | 364 | return rc; |
361 | } | 365 | } |
362 | 366 | ||
363 | /* Returns the CPU frequency corresponding to the pstate_id. */ | 367 | /* Returns the CPU frequency corresponding to the pstate_id. */ |
diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index d83939a1b3d4..4b0b50403901 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c | |||
@@ -10,18 +10,21 @@ | |||
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/of_address.h> | 11 | #include <linux/of_address.h> |
12 | #include <linux/of_platform.h> | 12 | #include <linux/of_platform.h> |
13 | #include <linux/pm_opp.h> | ||
13 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
14 | 15 | ||
15 | #define LUT_MAX_ENTRIES 40U | 16 | #define LUT_MAX_ENTRIES 40U |
16 | #define LUT_SRC GENMASK(31, 30) | 17 | #define LUT_SRC GENMASK(31, 30) |
17 | #define LUT_L_VAL GENMASK(7, 0) | 18 | #define LUT_L_VAL GENMASK(7, 0) |
18 | #define LUT_CORE_COUNT GENMASK(18, 16) | 19 | #define LUT_CORE_COUNT GENMASK(18, 16) |
20 | #define LUT_VOLT GENMASK(11, 0) | ||
19 | #define LUT_ROW_SIZE 32 | 21 | #define LUT_ROW_SIZE 32 |
20 | #define CLK_HW_DIV 2 | 22 | #define CLK_HW_DIV 2 |
21 | 23 | ||
22 | /* Register offsets */ | 24 | /* Register offsets */ |
23 | #define REG_ENABLE 0x0 | 25 | #define REG_ENABLE 0x0 |
24 | #define REG_LUT_TABLE 0x110 | 26 | #define REG_FREQ_LUT 0x110 |
27 | #define REG_VOLT_LUT 0x114 | ||
25 | #define REG_PERF_STATE 0x920 | 28 | #define REG_PERF_STATE 0x920 |
26 | 29 | ||
27 | static unsigned long cpu_hw_rate, xo_rate; | 30 | static unsigned long cpu_hw_rate, xo_rate; |
@@ -70,11 +73,12 @@ static unsigned int qcom_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, | |||
70 | return policy->freq_table[index].frequency; | 73 | return policy->freq_table[index].frequency; |
71 | } | 74 | } |
72 | 75 | ||
73 | static int qcom_cpufreq_hw_read_lut(struct device *dev, | 76 | static int qcom_cpufreq_hw_read_lut(struct device *cpu_dev, |
74 | struct cpufreq_policy *policy, | 77 | struct cpufreq_policy *policy, |
75 | void __iomem *base) | 78 | void __iomem *base) |
76 | { | 79 | { |
77 | u32 data, src, lval, i, core_count, prev_cc = 0, prev_freq = 0, freq; | 80 | u32 data, src, lval, i, core_count, prev_cc = 0, prev_freq = 0, freq; |
81 | u32 volt; | ||
78 | unsigned int max_cores = cpumask_weight(policy->cpus); | 82 | unsigned int max_cores = cpumask_weight(policy->cpus); |
79 | struct cpufreq_frequency_table *table; | 83 | struct cpufreq_frequency_table *table; |
80 | 84 | ||
@@ -83,23 +87,28 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev, | |||
83 | return -ENOMEM; | 87 | return -ENOMEM; |
84 | 88 | ||
85 | for (i = 0; i < LUT_MAX_ENTRIES; i++) { | 89 | for (i = 0; i < LUT_MAX_ENTRIES; i++) { |
86 | data = readl_relaxed(base + REG_LUT_TABLE + i * LUT_ROW_SIZE); | 90 | data = readl_relaxed(base + REG_FREQ_LUT + |
91 | i * LUT_ROW_SIZE); | ||
87 | src = FIELD_GET(LUT_SRC, data); | 92 | src = FIELD_GET(LUT_SRC, data); |
88 | lval = FIELD_GET(LUT_L_VAL, data); | 93 | lval = FIELD_GET(LUT_L_VAL, data); |
89 | core_count = FIELD_GET(LUT_CORE_COUNT, data); | 94 | core_count = FIELD_GET(LUT_CORE_COUNT, data); |
90 | 95 | ||
96 | data = readl_relaxed(base + REG_VOLT_LUT + | ||
97 | i * LUT_ROW_SIZE); | ||
98 | volt = FIELD_GET(LUT_VOLT, data) * 1000; | ||
99 | |||
91 | if (src) | 100 | if (src) |
92 | freq = xo_rate * lval / 1000; | 101 | freq = xo_rate * lval / 1000; |
93 | else | 102 | else |
94 | freq = cpu_hw_rate / 1000; | 103 | freq = cpu_hw_rate / 1000; |
95 | 104 | ||
96 | /* Ignore boosts in the middle of the table */ | 105 | if (freq != prev_freq && core_count == max_cores) { |
97 | if (core_count != max_cores) { | ||
98 | table[i].frequency = CPUFREQ_ENTRY_INVALID; | ||
99 | } else { | ||
100 | table[i].frequency = freq; | 106 | table[i].frequency = freq; |
101 | dev_dbg(dev, "index=%d freq=%d, core_count %d\n", i, | 107 | dev_pm_opp_add(cpu_dev, freq * 1000, volt); |
108 | dev_dbg(cpu_dev, "index=%d freq=%d, core_count %d\n", i, | ||
102 | freq, core_count); | 109 | freq, core_count); |
110 | } else { | ||
111 | table[i].frequency = CPUFREQ_ENTRY_INVALID; | ||
103 | } | 112 | } |
104 | 113 | ||
105 | /* | 114 | /* |
@@ -116,6 +125,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev, | |||
116 | if (prev_cc != max_cores) { | 125 | if (prev_cc != max_cores) { |
117 | prev->frequency = prev_freq; | 126 | prev->frequency = prev_freq; |
118 | prev->flags = CPUFREQ_BOOST_FREQ; | 127 | prev->flags = CPUFREQ_BOOST_FREQ; |
128 | dev_pm_opp_add(cpu_dev, prev_freq * 1000, volt); | ||
119 | } | 129 | } |
120 | 130 | ||
121 | break; | 131 | break; |
@@ -127,6 +137,7 @@ static int qcom_cpufreq_hw_read_lut(struct device *dev, | |||
127 | 137 | ||
128 | table[i].frequency = CPUFREQ_TABLE_END; | 138 | table[i].frequency = CPUFREQ_TABLE_END; |
129 | policy->freq_table = table; | 139 | policy->freq_table = table; |
140 | dev_pm_opp_set_sharing_cpus(cpu_dev, policy->cpus); | ||
130 | 141 | ||
131 | return 0; | 142 | return 0; |
132 | } | 143 | } |
@@ -159,10 +170,18 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) | |||
159 | struct device *dev = &global_pdev->dev; | 170 | struct device *dev = &global_pdev->dev; |
160 | struct of_phandle_args args; | 171 | struct of_phandle_args args; |
161 | struct device_node *cpu_np; | 172 | struct device_node *cpu_np; |
173 | struct device *cpu_dev; | ||
162 | struct resource *res; | 174 | struct resource *res; |
163 | void __iomem *base; | 175 | void __iomem *base; |
164 | int ret, index; | 176 | int ret, index; |
165 | 177 | ||
178 | cpu_dev = get_cpu_device(policy->cpu); | ||
179 | if (!cpu_dev) { | ||
180 | pr_err("%s: failed to get cpu%d device\n", __func__, | ||
181 | policy->cpu); | ||
182 | return -ENODEV; | ||
183 | } | ||
184 | |||
166 | cpu_np = of_cpu_device_node_get(policy->cpu); | 185 | cpu_np = of_cpu_device_node_get(policy->cpu); |
167 | if (!cpu_np) | 186 | if (!cpu_np) |
168 | return -EINVAL; | 187 | return -EINVAL; |
@@ -199,12 +218,21 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) | |||
199 | 218 | ||
200 | policy->driver_data = base + REG_PERF_STATE; | 219 | policy->driver_data = base + REG_PERF_STATE; |
201 | 220 | ||
202 | ret = qcom_cpufreq_hw_read_lut(dev, policy, base); | 221 | ret = qcom_cpufreq_hw_read_lut(cpu_dev, policy, base); |
203 | if (ret) { | 222 | if (ret) { |
204 | dev_err(dev, "Domain-%d failed to read LUT\n", index); | 223 | dev_err(dev, "Domain-%d failed to read LUT\n", index); |
205 | goto error; | 224 | goto error; |
206 | } | 225 | } |
207 | 226 | ||
227 | ret = dev_pm_opp_get_opp_count(cpu_dev); | ||
228 | if (ret <= 0) { | ||
229 | dev_err(cpu_dev, "Failed to add OPPs\n"); | ||
230 | ret = -ENODEV; | ||
231 | goto error; | ||
232 | } | ||
233 | |||
234 | dev_pm_opp_of_register_em(policy->cpus); | ||
235 | |||
208 | policy->fast_switch_possible = true; | 236 | policy->fast_switch_possible = true; |
209 | 237 | ||
210 | return 0; | 238 | return 0; |
@@ -215,8 +243,10 @@ error: | |||
215 | 243 | ||
216 | static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy) | 244 | static int qcom_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy) |
217 | { | 245 | { |
246 | struct device *cpu_dev = get_cpu_device(policy->cpu); | ||
218 | void __iomem *base = policy->driver_data - REG_PERF_STATE; | 247 | void __iomem *base = policy->driver_data - REG_PERF_STATE; |
219 | 248 | ||
249 | dev_pm_opp_remove_all_dynamic(cpu_dev); | ||
220 | kfree(policy->freq_table); | 250 | kfree(policy->freq_table); |
221 | devm_iounmap(&global_pdev->dev, base); | 251 | devm_iounmap(&global_pdev->dev, base); |
222 | 252 | ||
@@ -231,7 +261,8 @@ static struct freq_attr *qcom_cpufreq_hw_attr[] = { | |||
231 | 261 | ||
232 | static struct cpufreq_driver cpufreq_qcom_hw_driver = { | 262 | static struct cpufreq_driver cpufreq_qcom_hw_driver = { |
233 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | | 263 | .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
234 | CPUFREQ_HAVE_GOVERNOR_PER_POLICY, | 264 | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | |
265 | CPUFREQ_IS_COOLING_DEV, | ||
235 | .verify = cpufreq_generic_frequency_table_verify, | 266 | .verify = cpufreq_generic_frequency_table_verify, |
236 | .target_index = qcom_cpufreq_hw_target_index, | 267 | .target_index = qcom_cpufreq_hw_target_index, |
237 | .get = qcom_cpufreq_hw_get, | 268 | .get = qcom_cpufreq_hw_get, |
@@ -296,7 +327,7 @@ static int __init qcom_cpufreq_hw_init(void) | |||
296 | { | 327 | { |
297 | return platform_driver_register(&qcom_cpufreq_hw_driver); | 328 | return platform_driver_register(&qcom_cpufreq_hw_driver); |
298 | } | 329 | } |
299 | subsys_initcall(qcom_cpufreq_hw_init); | 330 | device_initcall(qcom_cpufreq_hw_init); |
300 | 331 | ||
301 | static void __exit qcom_cpufreq_hw_exit(void) | 332 | static void __exit qcom_cpufreq_hw_exit(void) |
302 | { | 333 | { |
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c index 2a3675c24032..1c8583cc06a2 100644 --- a/drivers/cpufreq/qcom-cpufreq-kryo.c +++ b/drivers/cpufreq/qcom-cpufreq-kryo.c | |||
@@ -42,7 +42,7 @@ enum _msm8996_version { | |||
42 | NUM_OF_MSM8996_VERSIONS, | 42 | NUM_OF_MSM8996_VERSIONS, |
43 | }; | 43 | }; |
44 | 44 | ||
45 | struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; | 45 | static struct platform_device *cpufreq_dt_pdev, *kryo_cpufreq_pdev; |
46 | 46 | ||
47 | static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) | 47 | static enum _msm8996_version qcom_cpufreq_kryo_get_msm_id(void) |
48 | { | 48 | { |
diff --git a/drivers/cpufreq/qoriq-cpufreq.c b/drivers/cpufreq/qoriq-cpufreq.c index 3d773f64b4df..4295e5476264 100644 --- a/drivers/cpufreq/qoriq-cpufreq.c +++ b/drivers/cpufreq/qoriq-cpufreq.c | |||
@@ -13,7 +13,6 @@ | |||
13 | #include <linux/clk.h> | 13 | #include <linux/clk.h> |
14 | #include <linux/clk-provider.h> | 14 | #include <linux/clk-provider.h> |
15 | #include <linux/cpufreq.h> | 15 | #include <linux/cpufreq.h> |
16 | #include <linux/cpu_cooling.h> | ||
17 | #include <linux/errno.h> | 16 | #include <linux/errno.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/kernel.h> | 18 | #include <linux/kernel.h> |
@@ -31,7 +30,6 @@ | |||
31 | struct cpu_data { | 30 | struct cpu_data { |
32 | struct clk **pclk; | 31 | struct clk **pclk; |
33 | struct cpufreq_frequency_table *table; | 32 | struct cpufreq_frequency_table *table; |
34 | struct thermal_cooling_device *cdev; | ||
35 | }; | 33 | }; |
36 | 34 | ||
37 | /* | 35 | /* |
@@ -239,7 +237,6 @@ static int qoriq_cpufreq_cpu_exit(struct cpufreq_policy *policy) | |||
239 | { | 237 | { |
240 | struct cpu_data *data = policy->driver_data; | 238 | struct cpu_data *data = policy->driver_data; |
241 | 239 | ||
242 | cpufreq_cooling_unregister(data->cdev); | ||
243 | kfree(data->pclk); | 240 | kfree(data->pclk); |
244 | kfree(data->table); | 241 | kfree(data->table); |
245 | kfree(data); | 242 | kfree(data); |
@@ -258,23 +255,15 @@ static int qoriq_cpufreq_target(struct cpufreq_policy *policy, | |||
258 | return clk_set_parent(policy->clk, parent); | 255 | return clk_set_parent(policy->clk, parent); |
259 | } | 256 | } |
260 | 257 | ||
261 | |||
262 | static void qoriq_cpufreq_ready(struct cpufreq_policy *policy) | ||
263 | { | ||
264 | struct cpu_data *cpud = policy->driver_data; | ||
265 | |||
266 | cpud->cdev = of_cpufreq_cooling_register(policy); | ||
267 | } | ||
268 | |||
269 | static struct cpufreq_driver qoriq_cpufreq_driver = { | 258 | static struct cpufreq_driver qoriq_cpufreq_driver = { |
270 | .name = "qoriq_cpufreq", | 259 | .name = "qoriq_cpufreq", |
271 | .flags = CPUFREQ_CONST_LOOPS, | 260 | .flags = CPUFREQ_CONST_LOOPS | |
261 | CPUFREQ_IS_COOLING_DEV, | ||
272 | .init = qoriq_cpufreq_cpu_init, | 262 | .init = qoriq_cpufreq_cpu_init, |
273 | .exit = qoriq_cpufreq_cpu_exit, | 263 | .exit = qoriq_cpufreq_cpu_exit, |
274 | .verify = cpufreq_generic_frequency_table_verify, | 264 | .verify = cpufreq_generic_frequency_table_verify, |
275 | .target_index = qoriq_cpufreq_target, | 265 | .target_index = qoriq_cpufreq_target, |
276 | .get = cpufreq_generic_get, | 266 | .get = cpufreq_generic_get, |
277 | .ready = qoriq_cpufreq_ready, | ||
278 | .attr = cpufreq_generic_attr, | 267 | .attr = cpufreq_generic_attr, |
279 | }; | 268 | }; |
280 | 269 | ||
diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index dbecd7667db2..5b4289460bc9 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c | |||
@@ -584,7 +584,7 @@ static struct notifier_block s5pv210_cpufreq_reboot_notifier = { | |||
584 | static int s5pv210_cpufreq_probe(struct platform_device *pdev) | 584 | static int s5pv210_cpufreq_probe(struct platform_device *pdev) |
585 | { | 585 | { |
586 | struct device_node *np; | 586 | struct device_node *np; |
587 | int id; | 587 | int id, result = 0; |
588 | 588 | ||
589 | /* | 589 | /* |
590 | * HACK: This is a temporary workaround to get access to clock | 590 | * HACK: This is a temporary workaround to get access to clock |
@@ -594,18 +594,39 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) | |||
594 | * this whole driver as soon as S5PV210 gets migrated to use | 594 | * this whole driver as soon as S5PV210 gets migrated to use |
595 | * cpufreq-dt driver. | 595 | * cpufreq-dt driver. |
596 | */ | 596 | */ |
597 | arm_regulator = regulator_get(NULL, "vddarm"); | ||
598 | if (IS_ERR(arm_regulator)) { | ||
599 | if (PTR_ERR(arm_regulator) == -EPROBE_DEFER) | ||
600 | pr_debug("vddarm regulator not ready, defer\n"); | ||
601 | else | ||
602 | pr_err("failed to get regulator vddarm\n"); | ||
603 | return PTR_ERR(arm_regulator); | ||
604 | } | ||
605 | |||
606 | int_regulator = regulator_get(NULL, "vddint"); | ||
607 | if (IS_ERR(int_regulator)) { | ||
608 | if (PTR_ERR(int_regulator) == -EPROBE_DEFER) | ||
609 | pr_debug("vddint regulator not ready, defer\n"); | ||
610 | else | ||
611 | pr_err("failed to get regulator vddint\n"); | ||
612 | result = PTR_ERR(int_regulator); | ||
613 | goto err_int_regulator; | ||
614 | } | ||
615 | |||
597 | np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock"); | 616 | np = of_find_compatible_node(NULL, NULL, "samsung,s5pv210-clock"); |
598 | if (!np) { | 617 | if (!np) { |
599 | pr_err("%s: failed to find clock controller DT node\n", | 618 | pr_err("%s: failed to find clock controller DT node\n", |
600 | __func__); | 619 | __func__); |
601 | return -ENODEV; | 620 | result = -ENODEV; |
621 | goto err_clock; | ||
602 | } | 622 | } |
603 | 623 | ||
604 | clk_base = of_iomap(np, 0); | 624 | clk_base = of_iomap(np, 0); |
605 | of_node_put(np); | 625 | of_node_put(np); |
606 | if (!clk_base) { | 626 | if (!clk_base) { |
607 | pr_err("%s: failed to map clock registers\n", __func__); | 627 | pr_err("%s: failed to map clock registers\n", __func__); |
608 | return -EFAULT; | 628 | result = -EFAULT; |
629 | goto err_clock; | ||
609 | } | 630 | } |
610 | 631 | ||
611 | for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") { | 632 | for_each_compatible_node(np, NULL, "samsung,s5pv210-dmc") { |
@@ -614,7 +635,8 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) | |||
614 | pr_err("%s: failed to get alias of dmc node '%pOFn'\n", | 635 | pr_err("%s: failed to get alias of dmc node '%pOFn'\n", |
615 | __func__, np); | 636 | __func__, np); |
616 | of_node_put(np); | 637 | of_node_put(np); |
617 | return id; | 638 | result = id; |
639 | goto err_clk_base; | ||
618 | } | 640 | } |
619 | 641 | ||
620 | dmc_base[id] = of_iomap(np, 0); | 642 | dmc_base[id] = of_iomap(np, 0); |
@@ -622,33 +644,40 @@ static int s5pv210_cpufreq_probe(struct platform_device *pdev) | |||
622 | pr_err("%s: failed to map dmc%d registers\n", | 644 | pr_err("%s: failed to map dmc%d registers\n", |
623 | __func__, id); | 645 | __func__, id); |
624 | of_node_put(np); | 646 | of_node_put(np); |
625 | return -EFAULT; | 647 | result = -EFAULT; |
648 | goto err_dmc; | ||
626 | } | 649 | } |
627 | } | 650 | } |
628 | 651 | ||
629 | for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) { | 652 | for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) { |
630 | if (!dmc_base[id]) { | 653 | if (!dmc_base[id]) { |
631 | pr_err("%s: failed to find dmc%d node\n", __func__, id); | 654 | pr_err("%s: failed to find dmc%d node\n", __func__, id); |
632 | return -ENODEV; | 655 | result = -ENODEV; |
656 | goto err_dmc; | ||
633 | } | 657 | } |
634 | } | 658 | } |
635 | 659 | ||
636 | arm_regulator = regulator_get(NULL, "vddarm"); | ||
637 | if (IS_ERR(arm_regulator)) { | ||
638 | pr_err("failed to get regulator vddarm\n"); | ||
639 | return PTR_ERR(arm_regulator); | ||
640 | } | ||
641 | |||
642 | int_regulator = regulator_get(NULL, "vddint"); | ||
643 | if (IS_ERR(int_regulator)) { | ||
644 | pr_err("failed to get regulator vddint\n"); | ||
645 | regulator_put(arm_regulator); | ||
646 | return PTR_ERR(int_regulator); | ||
647 | } | ||
648 | |||
649 | register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); | 660 | register_reboot_notifier(&s5pv210_cpufreq_reboot_notifier); |
650 | 661 | ||
651 | return cpufreq_register_driver(&s5pv210_driver); | 662 | return cpufreq_register_driver(&s5pv210_driver); |
663 | |||
664 | err_dmc: | ||
665 | for (id = 0; id < ARRAY_SIZE(dmc_base); ++id) | ||
666 | if (dmc_base[id]) { | ||
667 | iounmap(dmc_base[id]); | ||
668 | dmc_base[id] = NULL; | ||
669 | } | ||
670 | |||
671 | err_clk_base: | ||
672 | iounmap(clk_base); | ||
673 | |||
674 | err_clock: | ||
675 | regulator_put(int_regulator); | ||
676 | |||
677 | err_int_regulator: | ||
678 | regulator_put(arm_regulator); | ||
679 | |||
680 | return result; | ||
652 | } | 681 | } |
653 | 682 | ||
654 | static struct platform_driver s5pv210_cpufreq_platdrv = { | 683 | static struct platform_driver s5pv210_cpufreq_platdrv = { |
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c index 9ed46d188cb5..c47182fc64ea 100644 --- a/drivers/cpufreq/scmi-cpufreq.c +++ b/drivers/cpufreq/scmi-cpufreq.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <linux/cpu.h> | 11 | #include <linux/cpu.h> |
12 | #include <linux/cpufreq.h> | 12 | #include <linux/cpufreq.h> |
13 | #include <linux/cpumask.h> | 13 | #include <linux/cpumask.h> |
14 | #include <linux/cpu_cooling.h> | ||
15 | #include <linux/export.h> | 14 | #include <linux/export.h> |
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <linux/pm_opp.h> | 16 | #include <linux/pm_opp.h> |
@@ -22,7 +21,6 @@ | |||
22 | struct scmi_data { | 21 | struct scmi_data { |
23 | int domain_id; | 22 | int domain_id; |
24 | struct device *cpu_dev; | 23 | struct device *cpu_dev; |
25 | struct thermal_cooling_device *cdev; | ||
26 | }; | 24 | }; |
27 | 25 | ||
28 | static const struct scmi_handle *handle; | 26 | static const struct scmi_handle *handle; |
@@ -185,7 +183,6 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy) | |||
185 | { | 183 | { |
186 | struct scmi_data *priv = policy->driver_data; | 184 | struct scmi_data *priv = policy->driver_data; |
187 | 185 | ||
188 | cpufreq_cooling_unregister(priv->cdev); | ||
189 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); | 186 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); |
190 | dev_pm_opp_remove_all_dynamic(priv->cpu_dev); | 187 | dev_pm_opp_remove_all_dynamic(priv->cpu_dev); |
191 | kfree(priv); | 188 | kfree(priv); |
@@ -193,17 +190,11 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy) | |||
193 | return 0; | 190 | return 0; |
194 | } | 191 | } |
195 | 192 | ||
196 | static void scmi_cpufreq_ready(struct cpufreq_policy *policy) | ||
197 | { | ||
198 | struct scmi_data *priv = policy->driver_data; | ||
199 | |||
200 | priv->cdev = of_cpufreq_cooling_register(policy); | ||
201 | } | ||
202 | |||
203 | static struct cpufreq_driver scmi_cpufreq_driver = { | 193 | static struct cpufreq_driver scmi_cpufreq_driver = { |
204 | .name = "scmi", | 194 | .name = "scmi", |
205 | .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | | 195 | .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | |
206 | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | 196 | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
197 | CPUFREQ_IS_COOLING_DEV, | ||
207 | .verify = cpufreq_generic_frequency_table_verify, | 198 | .verify = cpufreq_generic_frequency_table_verify, |
208 | .attr = cpufreq_generic_attr, | 199 | .attr = cpufreq_generic_attr, |
209 | .target_index = scmi_cpufreq_set_target, | 200 | .target_index = scmi_cpufreq_set_target, |
@@ -211,7 +202,6 @@ static struct cpufreq_driver scmi_cpufreq_driver = { | |||
211 | .get = scmi_cpufreq_get_rate, | 202 | .get = scmi_cpufreq_get_rate, |
212 | .init = scmi_cpufreq_init, | 203 | .init = scmi_cpufreq_init, |
213 | .exit = scmi_cpufreq_exit, | 204 | .exit = scmi_cpufreq_exit, |
214 | .ready = scmi_cpufreq_ready, | ||
215 | }; | 205 | }; |
216 | 206 | ||
217 | static int scmi_cpufreq_probe(struct scmi_device *sdev) | 207 | static int scmi_cpufreq_probe(struct scmi_device *sdev) |
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 99449738faa4..1db2f6927e13 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/cpu.h> | 22 | #include <linux/cpu.h> |
23 | #include <linux/cpufreq.h> | 23 | #include <linux/cpufreq.h> |
24 | #include <linux/cpumask.h> | 24 | #include <linux/cpumask.h> |
25 | #include <linux/cpu_cooling.h> | ||
26 | #include <linux/export.h> | 25 | #include <linux/export.h> |
27 | #include <linux/module.h> | 26 | #include <linux/module.h> |
28 | #include <linux/of_platform.h> | 27 | #include <linux/of_platform.h> |
@@ -34,7 +33,6 @@ | |||
34 | struct scpi_data { | 33 | struct scpi_data { |
35 | struct clk *clk; | 34 | struct clk *clk; |
36 | struct device *cpu_dev; | 35 | struct device *cpu_dev; |
37 | struct thermal_cooling_device *cdev; | ||
38 | }; | 36 | }; |
39 | 37 | ||
40 | static struct scpi_ops *scpi_ops; | 38 | static struct scpi_ops *scpi_ops; |
@@ -186,7 +184,6 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy) | |||
186 | { | 184 | { |
187 | struct scpi_data *priv = policy->driver_data; | 185 | struct scpi_data *priv = policy->driver_data; |
188 | 186 | ||
189 | cpufreq_cooling_unregister(priv->cdev); | ||
190 | clk_put(priv->clk); | 187 | clk_put(priv->clk); |
191 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); | 188 | dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table); |
192 | kfree(priv); | 189 | kfree(priv); |
@@ -195,23 +192,16 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy) | |||
195 | return 0; | 192 | return 0; |
196 | } | 193 | } |
197 | 194 | ||
198 | static void scpi_cpufreq_ready(struct cpufreq_policy *policy) | ||
199 | { | ||
200 | struct scpi_data *priv = policy->driver_data; | ||
201 | |||
202 | priv->cdev = of_cpufreq_cooling_register(policy); | ||
203 | } | ||
204 | |||
205 | static struct cpufreq_driver scpi_cpufreq_driver = { | 195 | static struct cpufreq_driver scpi_cpufreq_driver = { |
206 | .name = "scpi-cpufreq", | 196 | .name = "scpi-cpufreq", |
207 | .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | | 197 | .flags = CPUFREQ_STICKY | CPUFREQ_HAVE_GOVERNOR_PER_POLICY | |
208 | CPUFREQ_NEED_INITIAL_FREQ_CHECK, | 198 | CPUFREQ_NEED_INITIAL_FREQ_CHECK | |
199 | CPUFREQ_IS_COOLING_DEV, | ||
209 | .verify = cpufreq_generic_frequency_table_verify, | 200 | .verify = cpufreq_generic_frequency_table_verify, |
210 | .attr = cpufreq_generic_attr, | 201 | .attr = cpufreq_generic_attr, |
211 | .get = scpi_cpufreq_get_rate, | 202 | .get = scpi_cpufreq_get_rate, |
212 | .init = scpi_cpufreq_init, | 203 | .init = scpi_cpufreq_init, |
213 | .exit = scpi_cpufreq_exit, | 204 | .exit = scpi_cpufreq_exit, |
214 | .ready = scpi_cpufreq_ready, | ||
215 | .target_index = scpi_cpufreq_set_target, | 205 | .target_index = scpi_cpufreq_set_target, |
216 | }; | 206 | }; |
217 | 207 | ||
diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index fbbcb88db061..5d8a09b82efb 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c | |||
@@ -243,8 +243,7 @@ static unsigned int speedstep_get(unsigned int cpu) | |||
243 | unsigned int speed; | 243 | unsigned int speed; |
244 | 244 | ||
245 | /* You're supposed to ensure CPU is online. */ | 245 | /* You're supposed to ensure CPU is online. */ |
246 | if (smp_call_function_single(cpu, get_freq_data, &speed, 1) != 0) | 246 | BUG_ON(smp_call_function_single(cpu, get_freq_data, &speed, 1)); |
247 | BUG(); | ||
248 | 247 | ||
249 | pr_debug("detected %u kHz as current frequency\n", speed); | 248 | pr_debug("detected %u kHz as current frequency\n", speed); |
250 | return speed; | 249 | return speed; |
diff --git a/drivers/cpufreq/tegra124-cpufreq.c b/drivers/cpufreq/tegra124-cpufreq.c index 43530254201a..4bb154f6c54c 100644 --- a/drivers/cpufreq/tegra124-cpufreq.c +++ b/drivers/cpufreq/tegra124-cpufreq.c | |||
@@ -134,6 +134,8 @@ static int tegra124_cpufreq_probe(struct platform_device *pdev) | |||
134 | 134 | ||
135 | platform_set_drvdata(pdev, priv); | 135 | platform_set_drvdata(pdev, priv); |
136 | 136 | ||
137 | of_node_put(np); | ||
138 | |||
137 | return 0; | 139 | return 0; |
138 | 140 | ||
139 | out_switch_to_pllx: | 141 | out_switch_to_pllx: |
diff --git a/drivers/opp/core.c b/drivers/opp/core.c index 18f1639dbc4a..4e00301060cf 100644 --- a/drivers/opp/core.c +++ b/drivers/opp/core.c | |||
@@ -533,9 +533,8 @@ static int _set_opp_voltage(struct device *dev, struct regulator *reg, | |||
533 | return ret; | 533 | return ret; |
534 | } | 534 | } |
535 | 535 | ||
536 | static inline int | 536 | static inline int _generic_set_opp_clk_only(struct device *dev, struct clk *clk, |
537 | _generic_set_opp_clk_only(struct device *dev, struct clk *clk, | 537 | unsigned long freq) |
538 | unsigned long old_freq, unsigned long freq) | ||
539 | { | 538 | { |
540 | int ret; | 539 | int ret; |
541 | 540 | ||
@@ -572,7 +571,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table, | |||
572 | } | 571 | } |
573 | 572 | ||
574 | /* Change frequency */ | 573 | /* Change frequency */ |
575 | ret = _generic_set_opp_clk_only(dev, opp_table->clk, old_freq, freq); | 574 | ret = _generic_set_opp_clk_only(dev, opp_table->clk, freq); |
576 | if (ret) | 575 | if (ret) |
577 | goto restore_voltage; | 576 | goto restore_voltage; |
578 | 577 | ||
@@ -586,7 +585,7 @@ static int _generic_set_opp_regulator(const struct opp_table *opp_table, | |||
586 | return 0; | 585 | return 0; |
587 | 586 | ||
588 | restore_freq: | 587 | restore_freq: |
589 | if (_generic_set_opp_clk_only(dev, opp_table->clk, freq, old_freq)) | 588 | if (_generic_set_opp_clk_only(dev, opp_table->clk, old_freq)) |
590 | dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", | 589 | dev_err(dev, "%s: failed to restore old-freq (%lu Hz)\n", |
591 | __func__, old_freq); | 590 | __func__, old_freq); |
592 | restore_voltage: | 591 | restore_voltage: |
@@ -759,7 +758,7 @@ int dev_pm_opp_set_rate(struct device *dev, unsigned long target_freq) | |||
759 | opp->supplies); | 758 | opp->supplies); |
760 | } else { | 759 | } else { |
761 | /* Only frequency scaling */ | 760 | /* Only frequency scaling */ |
762 | ret = _generic_set_opp_clk_only(dev, clk, old_freq, freq); | 761 | ret = _generic_set_opp_clk_only(dev, clk, freq); |
763 | } | 762 | } |
764 | 763 | ||
765 | /* Scaling down? Configure required OPPs after frequency */ | 764 | /* Scaling down? Configure required OPPs after frequency */ |
diff --git a/drivers/opp/of.c b/drivers/opp/of.c index 06f0f632ec47..cd58959e5158 100644 --- a/drivers/opp/of.c +++ b/drivers/opp/of.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/pm_domain.h> | 20 | #include <linux/pm_domain.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/export.h> | 22 | #include <linux/export.h> |
23 | #include <linux/energy_model.h> | ||
23 | 24 | ||
24 | #include "opp.h" | 25 | #include "opp.h" |
25 | 26 | ||
@@ -1047,3 +1048,101 @@ struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp) | |||
1047 | return of_node_get(opp->np); | 1048 | return of_node_get(opp->np); |
1048 | } | 1049 | } |
1049 | EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node); | 1050 | EXPORT_SYMBOL_GPL(dev_pm_opp_get_of_node); |
1051 | |||
1052 | /* | ||
1053 | * Callback function provided to the Energy Model framework upon registration. | ||
1054 | * This computes the power estimated by @CPU at @kHz if it is the frequency | ||
1055 | * of an existing OPP, or at the frequency of the first OPP above @kHz otherwise | ||
1056 | * (see dev_pm_opp_find_freq_ceil()). This function updates @kHz to the ceiled | ||
1057 | * frequency and @mW to the associated power. The power is estimated as | ||
1058 | * P = C * V^2 * f with C being the CPU's capacitance and V and f respectively | ||
1059 | * the voltage and frequency of the OPP. | ||
1060 | * | ||
1061 | * Returns -ENODEV if the CPU device cannot be found, -EINVAL if the power | ||
1062 | * calculation failed because of missing parameters, 0 otherwise. | ||
1063 | */ | ||
1064 | static int __maybe_unused _get_cpu_power(unsigned long *mW, unsigned long *kHz, | ||
1065 | int cpu) | ||
1066 | { | ||
1067 | struct device *cpu_dev; | ||
1068 | struct dev_pm_opp *opp; | ||
1069 | struct device_node *np; | ||
1070 | unsigned long mV, Hz; | ||
1071 | u32 cap; | ||
1072 | u64 tmp; | ||
1073 | int ret; | ||
1074 | |||
1075 | cpu_dev = get_cpu_device(cpu); | ||
1076 | if (!cpu_dev) | ||
1077 | return -ENODEV; | ||
1078 | |||
1079 | np = of_node_get(cpu_dev->of_node); | ||
1080 | if (!np) | ||
1081 | return -EINVAL; | ||
1082 | |||
1083 | ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap); | ||
1084 | of_node_put(np); | ||
1085 | if (ret) | ||
1086 | return -EINVAL; | ||
1087 | |||
1088 | Hz = *kHz * 1000; | ||
1089 | opp = dev_pm_opp_find_freq_ceil(cpu_dev, &Hz); | ||
1090 | if (IS_ERR(opp)) | ||
1091 | return -EINVAL; | ||
1092 | |||
1093 | mV = dev_pm_opp_get_voltage(opp) / 1000; | ||
1094 | dev_pm_opp_put(opp); | ||
1095 | if (!mV) | ||
1096 | return -EINVAL; | ||
1097 | |||
1098 | tmp = (u64)cap * mV * mV * (Hz / 1000000); | ||
1099 | do_div(tmp, 1000000000); | ||
1100 | |||
1101 | *mW = (unsigned long)tmp; | ||
1102 | *kHz = Hz / 1000; | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | |||
1107 | /** | ||
1108 | * dev_pm_opp_of_register_em() - Attempt to register an Energy Model | ||
1109 | * @cpus : CPUs for which an Energy Model has to be registered | ||
1110 | * | ||
1111 | * This checks whether the "dynamic-power-coefficient" devicetree property has | ||
1112 | * been specified, and tries to register an Energy Model with it if it has. | ||
1113 | */ | ||
1114 | void dev_pm_opp_of_register_em(struct cpumask *cpus) | ||
1115 | { | ||
1116 | struct em_data_callback em_cb = EM_DATA_CB(_get_cpu_power); | ||
1117 | int ret, nr_opp, cpu = cpumask_first(cpus); | ||
1118 | struct device *cpu_dev; | ||
1119 | struct device_node *np; | ||
1120 | u32 cap; | ||
1121 | |||
1122 | cpu_dev = get_cpu_device(cpu); | ||
1123 | if (!cpu_dev) | ||
1124 | return; | ||
1125 | |||
1126 | nr_opp = dev_pm_opp_get_opp_count(cpu_dev); | ||
1127 | if (nr_opp <= 0) | ||
1128 | return; | ||
1129 | |||
1130 | np = of_node_get(cpu_dev->of_node); | ||
1131 | if (!np) | ||
1132 | return; | ||
1133 | |||
1134 | /* | ||
1135 | * Register an EM only if the 'dynamic-power-coefficient' property is | ||
1136 | * set in devicetree. It is assumed the voltage values are known if that | ||
1137 | * property is set since it is useless otherwise. If voltages are not | ||
1138 | * known, just let the EM registration fail with an error to alert the | ||
1139 | * user about the inconsistent configuration. | ||
1140 | */ | ||
1141 | ret = of_property_read_u32(np, "dynamic-power-coefficient", &cap); | ||
1142 | of_node_put(np); | ||
1143 | if (ret || !cap) | ||
1144 | return; | ||
1145 | |||
1146 | em_register_perf_domain(cpus, nr_opp, &em_cb); | ||
1147 | } | ||
1148 | EXPORT_SYMBOL_GPL(dev_pm_opp_of_register_em); | ||
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index 30323426902e..58bb7d72dc2b 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig | |||
@@ -152,6 +152,7 @@ config CPU_THERMAL | |||
152 | bool "generic cpu cooling support" | 152 | bool "generic cpu cooling support" |
153 | depends on CPU_FREQ | 153 | depends on CPU_FREQ |
154 | depends on THERMAL_OF | 154 | depends on THERMAL_OF |
155 | depends on THERMAL=y | ||
155 | help | 156 | help |
156 | This implements the generic cpu cooling mechanism through frequency | 157 | This implements the generic cpu cooling mechanism through frequency |
157 | reduction. An ACPI version of this already exists | 158 | reduction. An ACPI version of this already exists |
diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h index 4f34734e7f36..ba6fd7202775 100644 --- a/include/acpi/cppc_acpi.h +++ b/include/acpi/cppc_acpi.h | |||
@@ -137,6 +137,7 @@ struct cppc_cpudata { | |||
137 | cpumask_var_t shared_cpu_map; | 137 | cpumask_var_t shared_cpu_map; |
138 | }; | 138 | }; |
139 | 139 | ||
140 | extern int cppc_get_desired_perf(int cpunum, u64 *desired_perf); | ||
140 | extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs); | 141 | extern int cppc_get_perf_ctrs(int cpu, struct cppc_perf_fb_ctrs *perf_fb_ctrs); |
141 | extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls); | 142 | extern int cppc_set_perf(int cpu, struct cppc_perf_ctrls *perf_ctrls); |
142 | extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps); | 143 | extern int cppc_get_perf_caps(int cpu, struct cppc_perf_caps *caps); |
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index c86d6d8bdfed..b160e98076e3 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h | |||
@@ -151,6 +151,9 @@ struct cpufreq_policy { | |||
151 | 151 | ||
152 | /* For cpufreq driver's internal use */ | 152 | /* For cpufreq driver's internal use */ |
153 | void *driver_data; | 153 | void *driver_data; |
154 | |||
155 | /* Pointer to the cooling device if used for thermal mitigation */ | ||
156 | struct thermal_cooling_device *cdev; | ||
154 | }; | 157 | }; |
155 | 158 | ||
156 | /* Only for ACPI */ | 159 | /* Only for ACPI */ |
@@ -254,20 +257,12 @@ __ATTR(_name, 0644, show_##_name, store_##_name) | |||
254 | static struct freq_attr _name = \ | 257 | static struct freq_attr _name = \ |
255 | __ATTR(_name, 0200, NULL, store_##_name) | 258 | __ATTR(_name, 0200, NULL, store_##_name) |
256 | 259 | ||
257 | struct global_attr { | ||
258 | struct attribute attr; | ||
259 | ssize_t (*show)(struct kobject *kobj, | ||
260 | struct attribute *attr, char *buf); | ||
261 | ssize_t (*store)(struct kobject *a, struct attribute *b, | ||
262 | const char *c, size_t count); | ||
263 | }; | ||
264 | |||
265 | #define define_one_global_ro(_name) \ | 260 | #define define_one_global_ro(_name) \ |
266 | static struct global_attr _name = \ | 261 | static struct kobj_attribute _name = \ |
267 | __ATTR(_name, 0444, show_##_name, NULL) | 262 | __ATTR(_name, 0444, show_##_name, NULL) |
268 | 263 | ||
269 | #define define_one_global_rw(_name) \ | 264 | #define define_one_global_rw(_name) \ |
270 | static struct global_attr _name = \ | 265 | static struct kobj_attribute _name = \ |
271 | __ATTR(_name, 0644, show_##_name, store_##_name) | 266 | __ATTR(_name, 0644, show_##_name, store_##_name) |
272 | 267 | ||
273 | 268 | ||
@@ -330,6 +325,8 @@ struct cpufreq_driver { | |||
330 | /* optional */ | 325 | /* optional */ |
331 | int (*bios_limit)(int cpu, unsigned int *limit); | 326 | int (*bios_limit)(int cpu, unsigned int *limit); |
332 | 327 | ||
328 | int (*online)(struct cpufreq_policy *policy); | ||
329 | int (*offline)(struct cpufreq_policy *policy); | ||
333 | int (*exit)(struct cpufreq_policy *policy); | 330 | int (*exit)(struct cpufreq_policy *policy); |
334 | void (*stop_cpu)(struct cpufreq_policy *policy); | 331 | void (*stop_cpu)(struct cpufreq_policy *policy); |
335 | int (*suspend)(struct cpufreq_policy *policy); | 332 | int (*suspend)(struct cpufreq_policy *policy); |
@@ -346,14 +343,15 @@ struct cpufreq_driver { | |||
346 | }; | 343 | }; |
347 | 344 | ||
348 | /* flags */ | 345 | /* flags */ |
349 | #define CPUFREQ_STICKY (1 << 0) /* driver isn't removed even if | 346 | |
350 | all ->init() calls failed */ | 347 | /* driver isn't removed even if all ->init() calls failed */ |
351 | #define CPUFREQ_CONST_LOOPS (1 << 1) /* loops_per_jiffy or other | 348 | #define CPUFREQ_STICKY BIT(0) |
352 | kernel "constants" aren't | 349 | |
353 | affected by frequency | 350 | /* loops_per_jiffy or other kernel "constants" aren't affected by frequency transitions */ |
354 | transitions */ | 351 | #define CPUFREQ_CONST_LOOPS BIT(1) |
355 | #define CPUFREQ_PM_NO_WARN (1 << 2) /* don't warn on suspend/resume | 352 | |
356 | speed mismatches */ | 353 | /* don't warn on suspend/resume speed mismatches */ |
354 | #define CPUFREQ_PM_NO_WARN BIT(2) | ||
357 | 355 | ||
358 | /* | 356 | /* |
359 | * This should be set by platforms having multiple clock-domains, i.e. | 357 | * This should be set by platforms having multiple clock-domains, i.e. |
@@ -361,14 +359,14 @@ struct cpufreq_driver { | |||
361 | * be created in cpu/cpu<num>/cpufreq/ directory and so they can use the same | 359 | * be created in cpu/cpu<num>/cpufreq/ directory and so they can use the same |
362 | * governor with different tunables for different clusters. | 360 | * governor with different tunables for different clusters. |
363 | */ | 361 | */ |
364 | #define CPUFREQ_HAVE_GOVERNOR_PER_POLICY (1 << 3) | 362 | #define CPUFREQ_HAVE_GOVERNOR_PER_POLICY BIT(3) |
365 | 363 | ||
366 | /* | 364 | /* |
367 | * Driver will do POSTCHANGE notifications from outside of their ->target() | 365 | * Driver will do POSTCHANGE notifications from outside of their ->target() |
368 | * routine and so must set cpufreq_driver->flags with this flag, so that core | 366 | * routine and so must set cpufreq_driver->flags with this flag, so that core |
369 | * can handle them specially. | 367 | * can handle them specially. |
370 | */ | 368 | */ |
371 | #define CPUFREQ_ASYNC_NOTIFICATION (1 << 4) | 369 | #define CPUFREQ_ASYNC_NOTIFICATION BIT(4) |
372 | 370 | ||
373 | /* | 371 | /* |
374 | * Set by drivers which want cpufreq core to check if CPU is running at a | 372 | * Set by drivers which want cpufreq core to check if CPU is running at a |
@@ -377,13 +375,19 @@ struct cpufreq_driver { | |||
377 | * from the table. And if that fails, we will stop further boot process by | 375 | * from the table. And if that fails, we will stop further boot process by |
378 | * issuing a BUG_ON(). | 376 | * issuing a BUG_ON(). |
379 | */ | 377 | */ |
380 | #define CPUFREQ_NEED_INITIAL_FREQ_CHECK (1 << 5) | 378 | #define CPUFREQ_NEED_INITIAL_FREQ_CHECK BIT(5) |
381 | 379 | ||
382 | /* | 380 | /* |
383 | * Set by drivers to disallow use of governors with "dynamic_switching" flag | 381 | * Set by drivers to disallow use of governors with "dynamic_switching" flag |
384 | * set. | 382 | * set. |
385 | */ | 383 | */ |
386 | #define CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING (1 << 6) | 384 | #define CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING BIT(6) |
385 | |||
386 | /* | ||
387 | * Set by drivers that want the core to automatically register the cpufreq | ||
388 | * driver as a thermal cooling device. | ||
389 | */ | ||
390 | #define CPUFREQ_IS_COOLING_DEV BIT(7) | ||
387 | 391 | ||
388 | int cpufreq_register_driver(struct cpufreq_driver *driver_data); | 392 | int cpufreq_register_driver(struct cpufreq_driver *driver_data); |
389 | int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); | 393 | int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); |
diff --git a/include/linux/platform_data/davinci-cpufreq.h b/include/linux/platform_data/davinci-cpufreq.h new file mode 100644 index 000000000000..3fbf9f2793b5 --- /dev/null +++ b/include/linux/platform_data/davinci-cpufreq.h | |||
@@ -0,0 +1,19 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
2 | /* | ||
3 | * TI DaVinci CPUFreq platform support. | ||
4 | * | ||
5 | * Copyright (C) 2009 Texas Instruments, Inc. http://www.ti.com/ | ||
6 | */ | ||
7 | |||
8 | #ifndef _MACH_DAVINCI_CPUFREQ_H | ||
9 | #define _MACH_DAVINCI_CPUFREQ_H | ||
10 | |||
11 | #include <linux/cpufreq.h> | ||
12 | |||
13 | struct davinci_cpufreq_config { | ||
14 | struct cpufreq_frequency_table *freq_table; | ||
15 | int (*set_voltage)(unsigned int index); | ||
16 | int (*init)(void); | ||
17 | }; | ||
18 | |||
19 | #endif /* _MACH_DAVINCI_CPUFREQ_H */ | ||
diff --git a/include/linux/pm_opp.h b/include/linux/pm_opp.h index b895f4e79868..c9c76310865a 100644 --- a/include/linux/pm_opp.h +++ b/include/linux/pm_opp.h | |||
@@ -327,6 +327,7 @@ int dev_pm_opp_of_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpuma | |||
327 | struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev); | 327 | struct device_node *dev_pm_opp_of_get_opp_desc_node(struct device *dev); |
328 | struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp); | 328 | struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp); |
329 | int of_get_required_opp_performance_state(struct device_node *np, int index); | 329 | int of_get_required_opp_performance_state(struct device_node *np, int index); |
330 | void dev_pm_opp_of_register_em(struct cpumask *cpus); | ||
330 | #else | 331 | #else |
331 | static inline int dev_pm_opp_of_add_table(struct device *dev) | 332 | static inline int dev_pm_opp_of_add_table(struct device *dev) |
332 | { | 333 | { |
@@ -365,6 +366,11 @@ static inline struct device_node *dev_pm_opp_get_of_node(struct dev_pm_opp *opp) | |||
365 | { | 366 | { |
366 | return NULL; | 367 | return NULL; |
367 | } | 368 | } |
369 | |||
370 | static inline void dev_pm_opp_of_register_em(struct cpumask *cpus) | ||
371 | { | ||
372 | } | ||
373 | |||
368 | static inline int of_get_required_opp_performance_state(struct device_node *np, int index) | 374 | static inline int of_get_required_opp_performance_state(struct device_node *np, int index) |
369 | { | 375 | { |
370 | return -ENOTSUPP; | 376 | return -ENOTSUPP; |