aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-07-30 05:27:01 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-07-30 05:27:01 -0400
commit5a4c996764da496afcc470a6e13dc23a8f55aca8 (patch)
tree3a4072147bcb22100ddad6c537aa8a890f32daf4
parentbafaf056e0734f7bca7d27716bb3c672e87bb0b1 (diff)
parent9b3d9bb3e4deef41095e513c2ffbebab20f9a982 (diff)
Merge back cpufreq material for 4.19.
-rw-r--r--Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt15
-rw-r--r--Documentation/trace/events-power.rst1
-rw-r--r--drivers/cpufreq/armada-37xx-cpufreq.c163
-rw-r--r--drivers/cpufreq/cppc_cpufreq.c52
-rw-r--r--drivers/cpufreq/cpufreq.c8
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c21
-rw-r--r--drivers/cpufreq/intel_pstate.c24
-rw-r--r--drivers/cpufreq/pcc-cpufreq.c9
-rw-r--r--drivers/cpufreq/qcom-cpufreq-kryo.c5
-rw-r--r--drivers/thermal/imx_thermal.c28
-rw-r--r--include/linux/cpu.h2
-rw-r--r--include/trace/events/power.h25
-rw-r--r--kernel/cpu.c6
13 files changed, 340 insertions, 19 deletions
diff --git a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
index 35c3c3460d17..eddde4faef01 100644
--- a/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
+++ b/Documentation/devicetree/bindings/arm/marvell/armada-37xx.txt
@@ -33,3 +33,18 @@ nb_pm: syscon@14000 {
33 compatible = "marvell,armada-3700-nb-pm", "syscon"; 33 compatible = "marvell,armada-3700-nb-pm", "syscon";
34 reg = <0x14000 0x60>; 34 reg = <0x14000 0x60>;
35} 35}
36
37AVS
38---
39
40For AVS an other component is needed:
41
42Required properties:
43- compatible : should contain "marvell,armada-3700-avs", "syscon";
44- reg : the register start and length for the AVS
45
46Example:
47avs: avs@11500 {
48 compatible = "marvell,armada-3700-avs", "syscon";
49 reg = <0x11500 0x40>;
50}
diff --git a/Documentation/trace/events-power.rst b/Documentation/trace/events-power.rst
index a77daca75e30..2ef318962e29 100644
--- a/Documentation/trace/events-power.rst
+++ b/Documentation/trace/events-power.rst
@@ -27,6 +27,7 @@ cpufreq.
27 27
28 cpu_idle "state=%lu cpu_id=%lu" 28 cpu_idle "state=%lu cpu_id=%lu"
29 cpu_frequency "state=%lu cpu_id=%lu" 29 cpu_frequency "state=%lu cpu_id=%lu"
30 cpu_frequency_limits "min=%lu max=%lu cpu_id=%lu"
30 31
31A suspend event is used to indicate the system going in and out of the 32A suspend event is used to indicate the system going in and out of the
32suspend mode: 33suspend mode:
diff --git a/drivers/cpufreq/armada-37xx-cpufreq.c b/drivers/cpufreq/armada-37xx-cpufreq.c
index 739da90ff3f6..75491fc841a6 100644
--- a/drivers/cpufreq/armada-37xx-cpufreq.c
+++ b/drivers/cpufreq/armada-37xx-cpufreq.c
@@ -51,6 +51,16 @@
51#define ARMADA_37XX_DVFS_LOAD_2 2 51#define ARMADA_37XX_DVFS_LOAD_2 2
52#define ARMADA_37XX_DVFS_LOAD_3 3 52#define ARMADA_37XX_DVFS_LOAD_3 3
53 53
54/* AVS register set */
55#define ARMADA_37XX_AVS_CTL0 0x0
56#define ARMADA_37XX_AVS_ENABLE BIT(30)
57#define ARMADA_37XX_AVS_HIGH_VDD_LIMIT 16
58#define ARMADA_37XX_AVS_LOW_VDD_LIMIT 22
59#define ARMADA_37XX_AVS_VDD_MASK 0x3F
60#define ARMADA_37XX_AVS_CTL2 0x8
61#define ARMADA_37XX_AVS_LOW_VDD_EN BIT(6)
62#define ARMADA_37XX_AVS_VSET(x) (0x1C + 4 * (x))
63
54/* 64/*
55 * On Armada 37xx the Power management manages 4 level of CPU load, 65 * On Armada 37xx the Power management manages 4 level of CPU load,
56 * each level can be associated with a CPU clock source, a CPU 66 * each level can be associated with a CPU clock source, a CPU
@@ -58,6 +68,17 @@
58 */ 68 */
59#define LOAD_LEVEL_NR 4 69#define LOAD_LEVEL_NR 4
60 70
71#define MIN_VOLT_MV 1000
72
73/* AVS value for the corresponding voltage (in mV) */
74static int avs_map[] = {
75 747, 758, 770, 782, 793, 805, 817, 828, 840, 852, 863, 875, 887, 898,
76 910, 922, 933, 945, 957, 968, 980, 992, 1003, 1015, 1027, 1038, 1050,
77 1062, 1073, 1085, 1097, 1108, 1120, 1132, 1143, 1155, 1167, 1178, 1190,
78 1202, 1213, 1225, 1237, 1248, 1260, 1272, 1283, 1295, 1307, 1318, 1330,
79 1342
80};
81
61struct armada37xx_cpufreq_state { 82struct armada37xx_cpufreq_state {
62 struct regmap *regmap; 83 struct regmap *regmap;
63 u32 nb_l0l1; 84 u32 nb_l0l1;
@@ -71,6 +92,7 @@ static struct armada37xx_cpufreq_state *armada37xx_cpufreq_state;
71struct armada_37xx_dvfs { 92struct armada_37xx_dvfs {
72 u32 cpu_freq_max; 93 u32 cpu_freq_max;
73 u8 divider[LOAD_LEVEL_NR]; 94 u8 divider[LOAD_LEVEL_NR];
95 u32 avs[LOAD_LEVEL_NR];
74}; 96};
75 97
76static struct armada_37xx_dvfs armada_37xx_dvfs[] = { 98static struct armada_37xx_dvfs armada_37xx_dvfs[] = {
@@ -148,6 +170,128 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
148 clk_set_parent(clk, parent); 170 clk_set_parent(clk, parent);
149} 171}
150 172
173/*
174 * Find out the armada 37x supported AVS value whose voltage value is
175 * the round-up closest to the target voltage value.
176 */
177static u32 armada_37xx_avs_val_match(int target_vm)
178{
179 u32 avs;
180
181 /* Find out the round-up closest supported voltage value */
182 for (avs = 0; avs < ARRAY_SIZE(avs_map); avs++)
183 if (avs_map[avs] >= target_vm)
184 break;
185
186 /*
187 * If all supported voltages are smaller than target one,
188 * choose the largest supported voltage
189 */
190 if (avs == ARRAY_SIZE(avs_map))
191 avs = ARRAY_SIZE(avs_map) - 1;
192
193 return avs;
194}
195
196/*
197 * For Armada 37xx soc, L0(VSET0) VDD AVS value is set to SVC revision
198 * value or a default value when SVC is not supported.
199 * - L0 can be read out from the register of AVS_CTRL_0 and L0 voltage
200 * can be got from the mapping table of avs_map.
201 * - L1 voltage should be about 100mv smaller than L0 voltage
202 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
203 * This function calculates L1 & L2 & L3 AVS values dynamically based
204 * on L0 voltage and fill all AVS values to the AVS value table.
205 */
206static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
207 struct armada_37xx_dvfs *dvfs)
208{
209 unsigned int target_vm;
210 int load_level = 0;
211 u32 l0_vdd_min;
212
213 if (base == NULL)
214 return;
215
216 /* Get L0 VDD min value */
217 regmap_read(base, ARMADA_37XX_AVS_CTL0, &l0_vdd_min);
218 l0_vdd_min = (l0_vdd_min >> ARMADA_37XX_AVS_LOW_VDD_LIMIT) &
219 ARMADA_37XX_AVS_VDD_MASK;
220 if (l0_vdd_min >= ARRAY_SIZE(avs_map)) {
221 pr_err("L0 VDD MIN %d is not correct.\n", l0_vdd_min);
222 return;
223 }
224 dvfs->avs[0] = l0_vdd_min;
225
226 if (avs_map[l0_vdd_min] <= MIN_VOLT_MV) {
227 /*
228 * If L0 voltage is smaller than 1000mv, then all VDD sets
229 * use L0 voltage;
230 */
231 u32 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV);
232
233 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)
234 dvfs->avs[load_level] = avs_min;
235
236 return;
237 }
238
239 /*
240 * L1 voltage is equal to L0 voltage - 100mv and it must be
241 * larger than 1000mv
242 */
243
244 target_vm = avs_map[l0_vdd_min] - 100;
245 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
246 dvfs->avs[1] = armada_37xx_avs_val_match(target_vm);
247
248 /*
249 * L2 & L3 voltage is equal to L0 voltage - 150mv and it must
250 * be larger than 1000mv
251 */
252 target_vm = avs_map[l0_vdd_min] - 150;
253 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
254 dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm);
255}
256
257static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
258 struct armada_37xx_dvfs *dvfs)
259{
260 unsigned int avs_val = 0, freq;
261 int load_level = 0;
262
263 if (base == NULL)
264 return;
265
266 /* Disable AVS before the configuration */
267 regmap_update_bits(base, ARMADA_37XX_AVS_CTL0,
268 ARMADA_37XX_AVS_ENABLE, 0);
269
270
271 /* Enable low voltage mode */
272 regmap_update_bits(base, ARMADA_37XX_AVS_CTL2,
273 ARMADA_37XX_AVS_LOW_VDD_EN,
274 ARMADA_37XX_AVS_LOW_VDD_EN);
275
276
277 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++) {
278 freq = dvfs->cpu_freq_max / dvfs->divider[load_level];
279
280 avs_val = dvfs->avs[load_level];
281 regmap_update_bits(base, ARMADA_37XX_AVS_VSET(load_level-1),
282 ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_HIGH_VDD_LIMIT |
283 ARMADA_37XX_AVS_VDD_MASK << ARMADA_37XX_AVS_LOW_VDD_LIMIT,
284 avs_val << ARMADA_37XX_AVS_HIGH_VDD_LIMIT |
285 avs_val << ARMADA_37XX_AVS_LOW_VDD_LIMIT);
286 }
287
288 /* Enable AVS after the configuration */
289 regmap_update_bits(base, ARMADA_37XX_AVS_CTL0,
290 ARMADA_37XX_AVS_ENABLE,
291 ARMADA_37XX_AVS_ENABLE);
292
293}
294
151static void armada37xx_cpufreq_disable_dvfs(struct regmap *base) 295static void armada37xx_cpufreq_disable_dvfs(struct regmap *base)
152{ 296{
153 unsigned int reg = ARMADA_37XX_NB_DYN_MOD, 297 unsigned int reg = ARMADA_37XX_NB_DYN_MOD,
@@ -216,7 +360,7 @@ static int __init armada37xx_cpufreq_driver_init(void)
216 struct platform_device *pdev; 360 struct platform_device *pdev;
217 unsigned long freq; 361 unsigned long freq;
218 unsigned int cur_frequency; 362 unsigned int cur_frequency;
219 struct regmap *nb_pm_base; 363 struct regmap *nb_pm_base, *avs_base;
220 struct device *cpu_dev; 364 struct device *cpu_dev;
221 int load_lvl, ret; 365 int load_lvl, ret;
222 struct clk *clk; 366 struct clk *clk;
@@ -227,6 +371,14 @@ static int __init armada37xx_cpufreq_driver_init(void)
227 if (IS_ERR(nb_pm_base)) 371 if (IS_ERR(nb_pm_base))
228 return -ENODEV; 372 return -ENODEV;
229 373
374 avs_base =
375 syscon_regmap_lookup_by_compatible("marvell,armada-3700-avs");
376
377 /* if AVS is not present don't use it but still try to setup dvfs */
378 if (IS_ERR(avs_base)) {
379 pr_info("Syscon failed for Adapting Voltage Scaling: skip it\n");
380 avs_base = NULL;
381 }
230 /* Before doing any configuration on the DVFS first, disable it */ 382 /* Before doing any configuration on the DVFS first, disable it */
231 armada37xx_cpufreq_disable_dvfs(nb_pm_base); 383 armada37xx_cpufreq_disable_dvfs(nb_pm_base);
232 384
@@ -270,16 +422,21 @@ static int __init armada37xx_cpufreq_driver_init(void)
270 422
271 armada37xx_cpufreq_state->regmap = nb_pm_base; 423 armada37xx_cpufreq_state->regmap = nb_pm_base;
272 424
425 armada37xx_cpufreq_avs_configure(avs_base, dvfs);
426 armada37xx_cpufreq_avs_setup(avs_base, dvfs);
427
273 armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider); 428 armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
274 clk_put(clk); 429 clk_put(clk);
275 430
276 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; 431 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
277 load_lvl++) { 432 load_lvl++) {
433 unsigned long u_volt = avs_map[dvfs->avs[load_lvl]] * 1000;
278 freq = cur_frequency / dvfs->divider[load_lvl]; 434 freq = cur_frequency / dvfs->divider[load_lvl];
279 435 ret = dev_pm_opp_add(cpu_dev, freq, u_volt);
280 ret = dev_pm_opp_add(cpu_dev, freq, 0);
281 if (ret) 436 if (ret)
282 goto remove_opp; 437 goto remove_opp;
438
439
283 } 440 }
284 441
285 /* Now that everything is setup, enable the DVFS at hardware level */ 442 /* Now that everything is setup, enable the DVFS at hardware level */
diff --git a/drivers/cpufreq/cppc_cpufreq.c b/drivers/cpufreq/cppc_cpufreq.c
index a9d3eec32795..30f302149730 100644
--- a/drivers/cpufreq/cppc_cpufreq.c
+++ b/drivers/cpufreq/cppc_cpufreq.c
@@ -296,10 +296,62 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy)
296 return ret; 296 return ret;
297} 297}
298 298
299static inline u64 get_delta(u64 t1, u64 t0)
300{
301 if (t1 > t0 || t0 > ~(u32)0)
302 return t1 - t0;
303
304 return (u32)t1 - (u32)t0;
305}
306
307static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu,
308 struct cppc_perf_fb_ctrs fb_ctrs_t0,
309 struct cppc_perf_fb_ctrs fb_ctrs_t1)
310{
311 u64 delta_reference, delta_delivered;
312 u64 reference_perf, delivered_perf;
313
314 reference_perf = fb_ctrs_t0.reference_perf;
315
316 delta_reference = get_delta(fb_ctrs_t1.reference,
317 fb_ctrs_t0.reference);
318 delta_delivered = get_delta(fb_ctrs_t1.delivered,
319 fb_ctrs_t0.delivered);
320
321 /* Check to avoid divide-by zero */
322 if (delta_reference || delta_delivered)
323 delivered_perf = (reference_perf * delta_delivered) /
324 delta_reference;
325 else
326 delivered_perf = cpu->perf_ctrls.desired_perf;
327
328 return cppc_cpufreq_perf_to_khz(cpu, delivered_perf);
329}
330
331static unsigned int cppc_cpufreq_get_rate(unsigned int cpunum)
332{
333 struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0};
334 struct cppc_cpudata *cpu = all_cpu_data[cpunum];
335 int ret;
336
337 ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t0);
338 if (ret)
339 return ret;
340
341 udelay(2); /* 2usec delay between sampling */
342
343 ret = cppc_get_perf_ctrs(cpunum, &fb_ctrs_t1);
344 if (ret)
345 return ret;
346
347 return cppc_get_rate_from_fbctrs(cpu, fb_ctrs_t0, fb_ctrs_t1);
348}
349
299static struct cpufreq_driver cppc_cpufreq_driver = { 350static struct cpufreq_driver cppc_cpufreq_driver = {
300 .flags = CPUFREQ_CONST_LOOPS, 351 .flags = CPUFREQ_CONST_LOOPS,
301 .verify = cppc_verify_policy, 352 .verify = cppc_verify_policy,
302 .target = cppc_cpufreq_set_target, 353 .target = cppc_cpufreq_set_target,
354 .get = cppc_cpufreq_get_rate,
303 .init = cppc_cpufreq_cpu_init, 355 .init = cppc_cpufreq_cpu_init,
304 .stop_cpu = cppc_cpufreq_stop_cpu, 356 .stop_cpu = cppc_cpufreq_stop_cpu,
305 .name = "cppc_cpufreq", 357 .name = "cppc_cpufreq",
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index b0dfd3222013..f53fb41efb7b 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -923,7 +923,12 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr,
923 struct freq_attr *fattr = to_attr(attr); 923 struct freq_attr *fattr = to_attr(attr);
924 ssize_t ret = -EINVAL; 924 ssize_t ret = -EINVAL;
925 925
926 cpus_read_lock(); 926 /*
927 * cpus_read_trylock() is used here to work around a circular lock
928 * dependency problem with respect to the cpufreq_register_driver().
929 */
930 if (!cpus_read_trylock())
931 return -EBUSY;
927 932
928 if (cpu_online(policy->cpu)) { 933 if (cpu_online(policy->cpu)) {
929 down_write(&policy->rwsem); 934 down_write(&policy->rwsem);
@@ -2236,6 +2241,7 @@ static int cpufreq_set_policy(struct cpufreq_policy *policy,
2236 2241
2237 policy->min = new_policy->min; 2242 policy->min = new_policy->min;
2238 policy->max = new_policy->max; 2243 policy->max = new_policy->max;
2244 trace_cpu_frequency_limits(policy);
2239 2245
2240 policy->cached_target_freq = UINT_MAX; 2246 policy->cached_target_freq = UINT_MAX;
2241 2247
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 8b3c2a79ad6c..b2ff423ad7f8 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -9,6 +9,7 @@
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>
12#include <linux/err.h> 13#include <linux/err.h>
13#include <linux/module.h> 14#include <linux/module.h>
14#include <linux/of.h> 15#include <linux/of.h>
@@ -50,6 +51,7 @@ static struct clk_bulk_data clks[] = {
50}; 51};
51 52
52static struct device *cpu_dev; 53static struct device *cpu_dev;
54static struct thermal_cooling_device *cdev;
53static bool free_opp; 55static bool free_opp;
54static struct cpufreq_frequency_table *freq_table; 56static struct cpufreq_frequency_table *freq_table;
55static unsigned int max_freq; 57static unsigned int max_freq;
@@ -191,6 +193,16 @@ static int imx6q_set_target(struct cpufreq_policy *policy, unsigned int index)
191 return 0; 193 return 0;
192} 194}
193 195
196static 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
194static int imx6q_cpufreq_init(struct cpufreq_policy *policy) 206static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
195{ 207{
196 int ret; 208 int ret;
@@ -202,13 +214,22 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
202 return ret; 214 return ret;
203} 215}
204 216
217static int imx6q_cpufreq_exit(struct cpufreq_policy *policy)
218{
219 cpufreq_cooling_unregister(cdev);
220
221 return 0;
222}
223
205static struct cpufreq_driver imx6q_cpufreq_driver = { 224static struct cpufreq_driver imx6q_cpufreq_driver = {
206 .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK, 225 .flags = CPUFREQ_NEED_INITIAL_FREQ_CHECK,
207 .verify = cpufreq_generic_frequency_table_verify, 226 .verify = cpufreq_generic_frequency_table_verify,
208 .target_index = imx6q_set_target, 227 .target_index = imx6q_set_target,
209 .get = cpufreq_generic_get, 228 .get = cpufreq_generic_get,
210 .init = imx6q_cpufreq_init, 229 .init = imx6q_cpufreq_init,
230 .exit = imx6q_cpufreq_exit,
211 .name = "imx6q-cpufreq", 231 .name = "imx6q-cpufreq",
232 .ready = imx6q_cpufreq_ready,
212 .attr = cpufreq_generic_attr, 233 .attr = cpufreq_generic_attr,
213 .suspend = cpufreq_generic_suspend, 234 .suspend = cpufreq_generic_suspend,
214}; 235};
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c
index 3c3971256130..b6139a7b49f6 100644
--- a/drivers/cpufreq/intel_pstate.c
+++ b/drivers/cpufreq/intel_pstate.c
@@ -657,21 +657,18 @@ static ssize_t store_energy_performance_preference(
657{ 657{
658 struct cpudata *cpu_data = all_cpu_data[policy->cpu]; 658 struct cpudata *cpu_data = all_cpu_data[policy->cpu];
659 char str_preference[21]; 659 char str_preference[21];
660 int ret, i = 0; 660 int ret;
661 661
662 ret = sscanf(buf, "%20s", str_preference); 662 ret = sscanf(buf, "%20s", str_preference);
663 if (ret != 1) 663 if (ret != 1)
664 return -EINVAL; 664 return -EINVAL;
665 665
666 while (energy_perf_strings[i] != NULL) { 666 ret = match_string(energy_perf_strings, -1, str_preference);
667 if (!strcmp(str_preference, energy_perf_strings[i])) { 667 if (ret < 0)
668 intel_pstate_set_energy_pref_index(cpu_data, i); 668 return ret;
669 return count;
670 }
671 ++i;
672 }
673 669
674 return -EINVAL; 670 intel_pstate_set_energy_pref_index(cpu_data, ret);
671 return count;
675} 672}
676 673
677static ssize_t show_energy_performance_preference( 674static ssize_t show_energy_performance_preference(
@@ -2072,6 +2069,15 @@ static int __intel_pstate_cpu_init(struct cpufreq_policy *policy)
2072 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate; 2069 cpu->pstate.max_pstate : cpu->pstate.turbo_pstate;
2073 policy->cpuinfo.max_freq *= cpu->pstate.scaling; 2070 policy->cpuinfo.max_freq *= cpu->pstate.scaling;
2074 2071
2072 if (hwp_active) {
2073 unsigned int max_freq;
2074
2075 max_freq = global.turbo_disabled ?
2076 cpu->pstate.max_freq : cpu->pstate.turbo_freq;
2077 if (max_freq < policy->cpuinfo.max_freq)
2078 policy->cpuinfo.max_freq = max_freq;
2079 }
2080
2075 intel_pstate_init_acpi_perf_limits(policy); 2081 intel_pstate_init_acpi_perf_limits(policy);
2076 2082
2077 policy->fast_switch_possible = true; 2083 policy->fast_switch_possible = true;
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index 0c56c9759672..099a849396f6 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -593,6 +593,15 @@ static int __init pcc_cpufreq_init(void)
593 return ret; 593 return ret;
594 } 594 }
595 595
596 if (num_present_cpus() > 4) {
597 pcc_cpufreq_driver.flags |= CPUFREQ_NO_AUTO_DYNAMIC_SWITCHING;
598 pr_err("%s: Too many CPUs, dynamic performance scaling disabled\n",
599 __func__);
600 pr_err("%s: Try to enable another scaling driver through BIOS settings\n",
601 __func__);
602 pr_err("%s: and complain to the system vendor\n", __func__);
603 }
604
596 ret = cpufreq_register_driver(&pcc_cpufreq_driver); 605 ret = cpufreq_register_driver(&pcc_cpufreq_driver);
597 606
598 return ret; 607 return ret;
diff --git a/drivers/cpufreq/qcom-cpufreq-kryo.c b/drivers/cpufreq/qcom-cpufreq-kryo.c
index efc9a7ae4857..a1830fa25fc5 100644
--- a/drivers/cpufreq/qcom-cpufreq-kryo.c
+++ b/drivers/cpufreq/qcom-cpufreq-kryo.c
@@ -109,8 +109,9 @@ static int qcom_cpufreq_kryo_probe(struct platform_device *pdev)
109 speedbin_nvmem = of_nvmem_cell_get(np, NULL); 109 speedbin_nvmem = of_nvmem_cell_get(np, NULL);
110 of_node_put(np); 110 of_node_put(np);
111 if (IS_ERR(speedbin_nvmem)) { 111 if (IS_ERR(speedbin_nvmem)) {
112 dev_err(cpu_dev, "Could not get nvmem cell: %ld\n", 112 if (PTR_ERR(speedbin_nvmem) != -EPROBE_DEFER)
113 PTR_ERR(speedbin_nvmem)); 113 dev_err(cpu_dev, "Could not get nvmem cell: %ld\n",
114 PTR_ERR(speedbin_nvmem));
114 return PTR_ERR(speedbin_nvmem); 115 return PTR_ERR(speedbin_nvmem);
115 } 116 }
116 117
diff --git a/drivers/thermal/imx_thermal.c b/drivers/thermal/imx_thermal.c
index 334d98be03b9..cbfcca828cd7 100644
--- a/drivers/thermal/imx_thermal.c
+++ b/drivers/thermal/imx_thermal.c
@@ -3,6 +3,7 @@
3// Copyright 2013 Freescale Semiconductor, Inc. 3// Copyright 2013 Freescale Semiconductor, Inc.
4 4
5#include <linux/clk.h> 5#include <linux/clk.h>
6#include <linux/cpu.h>
6#include <linux/cpufreq.h> 7#include <linux/cpufreq.h>
7#include <linux/cpu_cooling.h> 8#include <linux/cpu_cooling.h>
8#include <linux/delay.h> 9#include <linux/delay.h>
@@ -644,6 +645,27 @@ static const struct of_device_id of_imx_thermal_match[] = {
644}; 645};
645MODULE_DEVICE_TABLE(of, of_imx_thermal_match); 646MODULE_DEVICE_TABLE(of, of_imx_thermal_match);
646 647
648/*
649 * Create cooling device in case no #cooling-cells property is available in
650 * CPU node
651 */
652static int imx_thermal_register_legacy_cooling(struct imx_thermal_data *data)
653{
654 struct device_node *np = of_get_cpu_node(data->policy->cpu, NULL);
655 int ret;
656
657 if (!np || !of_find_property(np, "#cooling-cells", NULL)) {
658 data->cdev = cpufreq_cooling_register(data->policy);
659 if (IS_ERR(data->cdev)) {
660 ret = PTR_ERR(data->cdev);
661 cpufreq_cpu_put(data->policy);
662 return ret;
663 }
664 }
665
666 return 0;
667}
668
647static int imx_thermal_probe(struct platform_device *pdev) 669static int imx_thermal_probe(struct platform_device *pdev)
648{ 670{
649 struct imx_thermal_data *data; 671 struct imx_thermal_data *data;
@@ -724,12 +746,10 @@ static int imx_thermal_probe(struct platform_device *pdev)
724 return -EPROBE_DEFER; 746 return -EPROBE_DEFER;
725 } 747 }
726 748
727 data->cdev = cpufreq_cooling_register(data->policy); 749 ret = imx_thermal_register_legacy_cooling(data);
728 if (IS_ERR(data->cdev)) { 750 if (ret) {
729 ret = PTR_ERR(data->cdev);
730 dev_err(&pdev->dev, 751 dev_err(&pdev->dev,
731 "failed to register cpufreq cooling device: %d\n", ret); 752 "failed to register cpufreq cooling device: %d\n", ret);
732 cpufreq_cpu_put(data->policy);
733 return ret; 753 return ret;
734 } 754 }
735 755
diff --git a/include/linux/cpu.h b/include/linux/cpu.h
index a97a63eef59f..e850bfea3e84 100644
--- a/include/linux/cpu.h
+++ b/include/linux/cpu.h
@@ -103,6 +103,7 @@ extern void cpus_write_lock(void);
103extern void cpus_write_unlock(void); 103extern void cpus_write_unlock(void);
104extern void cpus_read_lock(void); 104extern void cpus_read_lock(void);
105extern void cpus_read_unlock(void); 105extern void cpus_read_unlock(void);
106extern int cpus_read_trylock(void);
106extern void lockdep_assert_cpus_held(void); 107extern void lockdep_assert_cpus_held(void);
107extern void cpu_hotplug_disable(void); 108extern void cpu_hotplug_disable(void);
108extern void cpu_hotplug_enable(void); 109extern void cpu_hotplug_enable(void);
@@ -115,6 +116,7 @@ static inline void cpus_write_lock(void) { }
115static inline void cpus_write_unlock(void) { } 116static inline void cpus_write_unlock(void) { }
116static inline void cpus_read_lock(void) { } 117static inline void cpus_read_lock(void) { }
117static inline void cpus_read_unlock(void) { } 118static inline void cpus_read_unlock(void) { }
119static inline int cpus_read_trylock(void) { return true; }
118static inline void lockdep_assert_cpus_held(void) { } 120static inline void lockdep_assert_cpus_held(void) { }
119static inline void cpu_hotplug_disable(void) { } 121static inline void cpu_hotplug_disable(void) { }
120static inline void cpu_hotplug_enable(void) { } 122static inline void cpu_hotplug_enable(void) { }
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 908977d69783..f7aece721aed 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -5,6 +5,7 @@
5#if !defined(_TRACE_POWER_H) || defined(TRACE_HEADER_MULTI_READ) 5#if !defined(_TRACE_POWER_H) || defined(TRACE_HEADER_MULTI_READ)
6#define _TRACE_POWER_H 6#define _TRACE_POWER_H
7 7
8#include <linux/cpufreq.h>
8#include <linux/ktime.h> 9#include <linux/ktime.h>
9#include <linux/pm_qos.h> 10#include <linux/pm_qos.h>
10#include <linux/tracepoint.h> 11#include <linux/tracepoint.h>
@@ -148,6 +149,30 @@ DEFINE_EVENT(cpu, cpu_frequency,
148 TP_ARGS(frequency, cpu_id) 149 TP_ARGS(frequency, cpu_id)
149); 150);
150 151
152TRACE_EVENT(cpu_frequency_limits,
153
154 TP_PROTO(struct cpufreq_policy *policy),
155
156 TP_ARGS(policy),
157
158 TP_STRUCT__entry(
159 __field(u32, min_freq)
160 __field(u32, max_freq)
161 __field(u32, cpu_id)
162 ),
163
164 TP_fast_assign(
165 __entry->min_freq = policy->min;
166 __entry->max_freq = policy->max;
167 __entry->cpu_id = policy->cpu;
168 ),
169
170 TP_printk("min=%lu max=%lu cpu_id=%lu",
171 (unsigned long)__entry->min_freq,
172 (unsigned long)__entry->max_freq,
173 (unsigned long)__entry->cpu_id)
174);
175
151TRACE_EVENT(device_pm_callback_start, 176TRACE_EVENT(device_pm_callback_start,
152 177
153 TP_PROTO(struct device *dev, const char *pm_ops, int event), 178 TP_PROTO(struct device *dev, const char *pm_ops, int event),
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 0db8938fbb23..307486baa477 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -290,6 +290,12 @@ void cpus_read_lock(void)
290} 290}
291EXPORT_SYMBOL_GPL(cpus_read_lock); 291EXPORT_SYMBOL_GPL(cpus_read_lock);
292 292
293int cpus_read_trylock(void)
294{
295 return percpu_down_read_trylock(&cpu_hotplug_lock);
296}
297EXPORT_SYMBOL_GPL(cpus_read_trylock);
298
293void cpus_read_unlock(void) 299void cpus_read_unlock(void)
294{ 300{
295 percpu_up_read(&cpu_hotplug_lock); 301 percpu_up_read(&cpu_hotplug_lock);