History

Merge branch 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Pull ARM cpufreq updates for v5.13 from Viresh Kumar: "- Fix typos in s5pv210 cpufreq driver (Bhaskar Chowdhury). - Armada 37xx: Fix cpufreq changing base CPU speed to 800 MHz from 1000 MHz (Pali Rohár and Marek Behún). - cpufreq-dt: Return -EPROBE_DEFER on failure to add table (Quanyang Wang). - Minor cleanup in cppc driver (Tom Saeger). - Add frequency invariance support for CPPC driver and generalize freq invariance support arch-topology driver (Viresh Kumar)." * 'cpufreq/arm/linux-next' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: cpufreq: armada-37xx: Fix module unloading cpufreq: armada-37xx: Remove cur_frequency variable cpufreq: armada-37xx: Fix determining base CPU frequency cpufreq: armada-37xx: Fix driver cleanup when registration failed clk: mvebu: armada-37xx-periph: Fix workaround for switching from L1 to L0 clk: mvebu: armada-37xx-periph: Fix switching CPU freq from 250 Mhz to 1 GHz cpufreq: armada-37xx: Fix the AVS value for load L1 clk: mvebu: armada-37xx-periph: remove .set_parent method for CPU PM clock cpufreq: armada-37xx: Fix setting TBG parent for load levels cpufreq: dt: dev_pm_opp_of_cpumask_add_table() may return -EPROBE_DEFER cpufreq: cppc: simplify default delay_us setting cpufreq: Rudimentary typos fix in the file s5pv210-cpufreq.c cpufreq: CPPC: Add support for frequency invariance arch_topology: Export arch_freq_scale and helpers arch_topology: Allow multiple entities to provide sched_freq_tick() callback arch_topology: Rename freq_scale as arch_freq_scale

Rafael J. Wysocki committed 5 years ago

Commit 0210b8e2 parents b989bc0 dbbd49b11 files · +534 −180Browse files

Unified · Split

11 files
  1. arch/arm64/include/asm/topology.h +1 −9
  2. arch/arm64/kernel/topology.c +41 −68
  3. drivers/base/arch_topology.c +83 −6
  4. drivers/clk/mvebu/armada-37xx-periph.c +45 −38
  5. drivers/cpufreq/Kconfig.arm +10 −0
  6. drivers/cpufreq/armada-37xx-cpufreq.c +88 −23
  7. drivers/cpufreq/cppc_cpufreq.c +235 −24
  8. drivers/cpufreq/cpufreq-dt.c +7 −2
  9. drivers/cpufreq/s5pv210-cpufreq.c +7 −7
  10. include/linux/arch_topology.h +16 −3
  11. kernel/sched/core.c +1 −0
arch/arm64/include/asm/topology.h+1−9
@@ -17,17 +17,9 @@ int pcibus_to_node(struct pci_bus *bus); · 16 unmodified lines
17#include <linux/arch_topology.h>17#include <linux/arch_topology.h>
18 18
19void update_freq_counters_refs(void);19void update_freq_counters_refs(void);
20void topology_scale_freq_tick(void);
21
22#ifdef CONFIG_ARM64_AMU_EXTN
23/*
24 * Replace task scheduler's default counter-based
25 * frequency-invariance scale factor setting.
26 */
27#define arch_scale_freq_tick topology_scale_freq_tick
28#endif /* CONFIG_ARM64_AMU_EXTN */
29 20
30/* Replace task scheduler's default frequency-invariant accounting */21/* Replace task scheduler's default frequency-invariant accounting */
22#define arch_scale_freq_tick topology_scale_freq_tick
31#define arch_set_freq_scale topology_set_freq_scale23#define arch_set_freq_scale topology_set_freq_scale
32#define arch_scale_freq_capacity topology_get_freq_scale24#define arch_scale_freq_capacity topology_get_freq_scale
33#define arch_scale_freq_invariant topology_scale_freq_invariant25#define arch_scale_freq_invariant topology_scale_freq_invariant
arch/arm64/kernel/topology.c+41−68
@@ -199,12 +199,47 @@ static int freq_inv_set_max_ratio(int cpu, u64 max_rate, u64 ref_rate) · 198 unmodified lines
199 return 0;199 return 0;
200}200}
201 201
202static DEFINE_STATIC_KEY_FALSE(amu_fie_key);202static void amu_scale_freq_tick(void)
203#define amu_freq_invariant() static_branch_unlikely(&amu_fie_key)203{
204 u64 prev_core_cnt, prev_const_cnt;
205 u64 core_cnt, const_cnt, scale;
206
207 prev_const_cnt = this_cpu_read(arch_const_cycles_prev);
208 prev_core_cnt = this_cpu_read(arch_core_cycles_prev);
209
210 update_freq_counters_refs();
211
212 const_cnt = this_cpu_read(arch_const_cycles_prev);
213 core_cnt = this_cpu_read(arch_core_cycles_prev);
214
215 if (unlikely(core_cnt <= prev_core_cnt ||
216 const_cnt <= prev_const_cnt))
217 return;
218
219 /*
220 * /\core arch_max_freq_scale
221 * scale = ------- * --------------------
222 * /\const SCHED_CAPACITY_SCALE
223 *
224 * See validate_cpu_freq_invariance_counters() for details on
225 * arch_max_freq_scale and the use of SCHED_CAPACITY_SHIFT.
226 */
227 scale = core_cnt - prev_core_cnt;
228 scale *= this_cpu_read(arch_max_freq_scale);
229 scale = div64_u64(scale >> SCHED_CAPACITY_SHIFT,
230 const_cnt - prev_const_cnt);
231
232 scale = min_t(unsigned long, scale, SCHED_CAPACITY_SCALE);
233 this_cpu_write(arch_freq_scale, (unsigned long)scale);
234}
235
236static struct scale_freq_data amu_sfd = {
237 .source = SCALE_FREQ_SOURCE_ARCH,
238 .set_freq_scale = amu_scale_freq_tick,
239};
204 240
205static void amu_fie_setup(const struct cpumask *cpus)241static void amu_fie_setup(const struct cpumask *cpus)
206{242{
207 bool invariant;
208 int cpu;243 int cpu;
209 244
210 /* We are already set since the last insmod of cpufreq driver */245 /* We are already set since the last insmod of cpufreq driver */
@@ -221,25 +256,10 @@ static void amu_fie_setup(const struct cpumask *cpus) · 10 unmodified lines
221 256
222 cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus);257 cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus);
223 258
224 invariant = topology_scale_freq_invariant();259 topology_set_scale_freq_source(&amu_sfd, amu_fie_cpus);
225
226 /* We aren't fully invariant yet */
227 if (!invariant && !cpumask_equal(amu_fie_cpus, cpu_present_mask))
228 return;
229
230 static_branch_enable(&amu_fie_key);
231 260
232 pr_debug("CPUs[%*pbl]: counters will be used for FIE.",261 pr_debug("CPUs[%*pbl]: counters will be used for FIE.",
233 cpumask_pr_args(cpus));262 cpumask_pr_args(cpus));
234
235 /*
236 * Task scheduler behavior depends on frequency invariance support,
237 * either cpufreq or counter driven. If the support status changes as
238 * a result of counter initialisation and use, retrigger the build of
239 * scheduling domains to ensure the information is propagated properly.
240 */
241 if (!invariant)
242 rebuild_sched_domains_energy();
243}263}
244 264
245static int init_amu_fie_callback(struct notifier_block *nb, unsigned long val,265static int init_amu_fie_callback(struct notifier_block *nb, unsigned long val,
@@ -256,8 +276,8 @@ static int init_amu_fie_callback(struct notifier_block *nb, unsigned long val, · 10 unmodified lines
256 * initialized AMU support and enabled invariance. The AMU counters will276 * initialized AMU support and enabled invariance. The AMU counters will
257 * keep on working just fine in the absence of the cpufreq driver, and277 * keep on working just fine in the absence of the cpufreq driver, and
258 * for the CPUs for which there are no counters available, the last set278 * for the CPUs for which there are no counters available, the last set
259 * value of freq_scale will remain valid as that is the frequency those279 * value of arch_freq_scale will remain valid as that is the frequency
260 * CPUs are running at.280 * those CPUs are running at.
261 */281 */
262 282
263 return 0;283 return 0;
@@ -283,53 +303,6 @@ static int __init init_amu_fie(void) · 19 unmodified lines
283}303}
284core_initcall(init_amu_fie);304core_initcall(init_amu_fie);
285 305
286bool arch_freq_counters_available(const struct cpumask *cpus)
287{
288 return amu_freq_invariant() &&
289 cpumask_subset(cpus, amu_fie_cpus);
290}
291
292void topology_scale_freq_tick(void)
293{
294 u64 prev_core_cnt, prev_const_cnt;
295 u64 core_cnt, const_cnt, scale;
296 int cpu = smp_processor_id();
297
298 if (!amu_freq_invariant())
299 return;
300
301 if (!cpumask_test_cpu(cpu, amu_fie_cpus))
302 return;
303
304 prev_const_cnt = this_cpu_read(arch_const_cycles_prev);
305 prev_core_cnt = this_cpu_read(arch_core_cycles_prev);
306
307 update_freq_counters_refs();
308
309 const_cnt = this_cpu_read(arch_const_cycles_prev);
310 core_cnt = this_cpu_read(arch_core_cycles_prev);
311
312 if (unlikely(core_cnt <= prev_core_cnt ||
313 const_cnt <= prev_const_cnt))
314 return;
315
316 /*
317 * /\core arch_max_freq_scale
318 * scale = ------- * --------------------
319 * /\const SCHED_CAPACITY_SCALE
320 *
321 * See validate_cpu_freq_invariance_counters() for details on
322 * arch_max_freq_scale and the use of SCHED_CAPACITY_SHIFT.
323 */
324 scale = core_cnt - prev_core_cnt;
325 scale *= this_cpu_read(arch_max_freq_scale);
326 scale = div64_u64(scale >> SCHED_CAPACITY_SHIFT,
327 const_cnt - prev_const_cnt);
328
329 scale = min_t(unsigned long, scale, SCHED_CAPACITY_SCALE);
330 this_cpu_write(freq_scale, (unsigned long)scale);
331}
332
333#ifdef CONFIG_ACPI_CPPC_LIB306#ifdef CONFIG_ACPI_CPPC_LIB
334#include <acpi/cppc_acpi.h>307#include <acpi/cppc_acpi.h>
335 308
drivers/base/arch_topology.c+83−6
@@ -21,17 +21,94 @@ · 20 unmodified lines
21#include <linux/sched.h>21#include <linux/sched.h>
22#include <linux/smp.h>22#include <linux/smp.h>
23 23
24static DEFINE_PER_CPU(struct scale_freq_data *, sft_data);
25static struct cpumask scale_freq_counters_mask;
26static bool scale_freq_invariant;
27
28static bool supports_scale_freq_counters(const struct cpumask *cpus)
29{
30 return cpumask_subset(cpus, &scale_freq_counters_mask);
31}
32
24bool topology_scale_freq_invariant(void)33bool topology_scale_freq_invariant(void)
25{34{
26 return cpufreq_supports_freq_invariance() ||35 return cpufreq_supports_freq_invariance() ||
27 arch_freq_counters_available(cpu_online_mask);36 supports_scale_freq_counters(cpu_online_mask);
28}37}
29 38
30__weak bool arch_freq_counters_available(const struct cpumask *cpus)39static void update_scale_freq_invariant(bool status)
31{40{
32 return false;41 if (scale_freq_invariant == status)
42 return;
43
44 /*
45 * Task scheduler behavior depends on frequency invariance support,
46 * either cpufreq or counter driven. If the support status changes as
47 * a result of counter initialisation and use, retrigger the build of
48 * scheduling domains to ensure the information is propagated properly.
49 */
50 if (topology_scale_freq_invariant() == status) {
51 scale_freq_invariant = status;
52 rebuild_sched_domains_energy();
53 }
33}54}
34DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;55
56void topology_set_scale_freq_source(struct scale_freq_data *data,
57 const struct cpumask *cpus)
58{
59 struct scale_freq_data *sfd;
60 int cpu;
61
62 /*
63 * Avoid calling rebuild_sched_domains() unnecessarily if FIE is
64 * supported by cpufreq.
65 */
66 if (cpumask_empty(&scale_freq_counters_mask))
67 scale_freq_invariant = topology_scale_freq_invariant();
68
69 for_each_cpu(cpu, cpus) {
70 sfd = per_cpu(sft_data, cpu);
71
72 /* Use ARCH provided counters whenever possible */
73 if (!sfd || sfd->source != SCALE_FREQ_SOURCE_ARCH) {
74 per_cpu(sft_data, cpu) = data;
75 cpumask_set_cpu(cpu, &scale_freq_counters_mask);
76 }
77 }
78
79 update_scale_freq_invariant(true);
80}
81EXPORT_SYMBOL_GPL(topology_set_scale_freq_source);
82
83void topology_clear_scale_freq_source(enum scale_freq_source source,
84 const struct cpumask *cpus)
85{
86 struct scale_freq_data *sfd;
87 int cpu;
88
89 for_each_cpu(cpu, cpus) {
90 sfd = per_cpu(sft_data, cpu);
91
92 if (sfd && sfd->source == source) {
93 per_cpu(sft_data, cpu) = NULL;
94 cpumask_clear_cpu(cpu, &scale_freq_counters_mask);
95 }
96 }
97
98 update_scale_freq_invariant(false);
99}
100EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source);
101
102void topology_scale_freq_tick(void)
103{
104 struct scale_freq_data *sfd = *this_cpu_ptr(&sft_data);
105
106 if (sfd)
107 sfd->set_freq_scale();
108}
109
110DEFINE_PER_CPU(unsigned long, arch_freq_scale) = SCHED_CAPACITY_SCALE;
111EXPORT_PER_CPU_SYMBOL_GPL(arch_freq_scale);
35 112
36void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,113void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,
37 unsigned long max_freq)114 unsigned long max_freq)
@@ -47,13 +124,13 @@ void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq, · 9 unmodified lines
47 * want to update the scale factor with information from CPUFREQ.124 * want to update the scale factor with information from CPUFREQ.
48 * Instead the scale factor will be updated from arch_scale_freq_tick.125 * Instead the scale factor will be updated from arch_scale_freq_tick.
49 */126 */
50 if (arch_freq_counters_available(cpus))127 if (supports_scale_freq_counters(cpus))
51 return;128 return;
52 129
53 scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;130 scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;
54 131
55 for_each_cpu(i, cpus)132 for_each_cpu(i, cpus)
56 per_cpu(freq_scale, i) = scale;133 per_cpu(arch_freq_scale, i) = scale;
57}134}
58 135
59DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;136DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE;
drivers/clk/mvebu/armada-37xx-periph.c+45−38
@@ -84,6 +84,7 @@ struct clk_pm_cpu { · 83 unmodified lines
84 void __iomem *reg_div;84 void __iomem *reg_div;
85 u8 shift_div;85 u8 shift_div;
86 struct regmap *nb_pm_base;86 struct regmap *nb_pm_base;
87 unsigned long l1_expiration;
87};88};
88 89
89#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)90#define to_clk_double_div(_hw) container_of(_hw, struct clk_double_div, hw)
@@ -440,33 +441,6 @@ static u8 clk_pm_cpu_get_parent(struct clk_hw *hw) · 350 unmodified lines
440 return val;441 return val;
441}442}
442 443
443static int clk_pm_cpu_set_parent(struct clk_hw *hw, u8 index)
444{
445 struct clk_pm_cpu *pm_cpu = to_clk_pm_cpu(hw);
446 struct regmap *base = pm_cpu->nb_pm_base;
447 int load_level;
448
449 /*
450 * We set the clock parent only if the DVFS is available but
451 * not enabled.
452 */
453 if (IS_ERR(base) || armada_3700_pm_dvfs_is_enabled(base))
454 return -EINVAL;
455
456 /* Set the parent clock for all the load level */
457 for (load_level = 0; load_level < LOAD_LEVEL_NR; load_level++) {
458 unsigned int reg, mask, val,
459 offset = ARMADA_37XX_NB_TBG_SEL_OFF;
460
461 armada_3700_pm_dvfs_update_regs(load_level, &reg, &offset);
462
463 val = index << offset;
464 mask = ARMADA_37XX_NB_TBG_SEL_MASK << offset;
465 regmap_update_bits(base, reg, mask, val);
466 }
467 return 0;
468}
469
470static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,444static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
471 unsigned long parent_rate)445 unsigned long parent_rate)
472{446{
@@ -514,8 +488,10 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, · 41 unmodified lines
514}488}
515 489
516/*490/*
517 * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz491 * Workaround when base CPU frequnecy is 1000 or 1200 MHz
518 * respectively) to L0 frequency (1.2 Ghz) requires a significant492 *
493 * Switching the CPU from the L2 or L3 frequencies (250/300 or 200 MHz
494 * respectively) to L0 frequency (1/1.2 GHz) requires a significant
519 * amount of time to let VDD stabilize to the appropriate495 * amount of time to let VDD stabilize to the appropriate
520 * voltage. This amount of time is large enough that it cannot be496 * voltage. This amount of time is large enough that it cannot be
521 * covered by the hardware countdown register. Due to this, the CPU497 * covered by the hardware countdown register. Due to this, the CPU
@@ -525,26 +501,56 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, · 3 unmodified lines
525 * To work around this problem, we prevent switching directly from the501 * To work around this problem, we prevent switching directly from the
526 * L2/L3 frequencies to the L0 frequency, and instead switch to the L1502 * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
527 * frequency in-between. The sequence therefore becomes:503 * frequency in-between. The sequence therefore becomes:
528 * 1. First switch from L2/L3(200/300MHz) to L1(600MHZ)504 * 1. First switch from L2/L3 (200/250/300 MHz) to L1 (500/600 MHz)
529 * 2. Sleep 20ms for stabling VDD voltage505 * 2. Sleep 20ms for stabling VDD voltage
530 * 3. Then switch from L1(600MHZ) to L0(1200Mhz).506 * 3. Then switch from L1 (500/600 MHz) to L0 (1000/1200 MHz).
531 */507 */
532static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)508static void clk_pm_cpu_set_rate_wa(struct clk_pm_cpu *pm_cpu,
509 unsigned int new_level, unsigned long rate,
510 struct regmap *base)
533{511{
534 unsigned int cur_level;512 unsigned int cur_level;
535 513
536 if (rate != 1200 * 1000 * 1000)
537 return;
538
539 regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);514 regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
540 cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;515 cur_level &= ARMADA_37XX_NB_CPU_LOAD_MASK;
541 if (cur_level <= ARMADA_37XX_DVFS_LOAD_1)516
517 if (cur_level == new_level)
518 return;
519
520 /*
521 * System wants to go to L1 on its own. If we are going from L2/L3,
522 * remember when 20ms will expire. If from L0, set the value so that
523 * next switch to L0 won't have to wait.
524 */
525 if (new_level == ARMADA_37XX_DVFS_LOAD_1) {
526 if (cur_level == ARMADA_37XX_DVFS_LOAD_0)
527 pm_cpu->l1_expiration = jiffies;
528 else
529 pm_cpu->l1_expiration = jiffies + msecs_to_jiffies(20);
542 return;530 return;
531 }
532
533 /*
534 * If we are setting to L2/L3, just invalidate L1 expiration time,
535 * sleeping is not needed.
536 */
537 if (rate < 1000*1000*1000)
538 goto invalidate_l1_exp;
539
540 /*
541 * We are going to L0 with rate >= 1GHz. Check whether we have been at
542 * L1 for long enough time. If not, go to L1 for 20ms.
543 */
544 if (pm_cpu->l1_expiration && jiffies >= pm_cpu->l1_expiration)
545 goto invalidate_l1_exp;
543 546
544 regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,547 regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
545 ARMADA_37XX_NB_CPU_LOAD_MASK,548 ARMADA_37XX_NB_CPU_LOAD_MASK,
546 ARMADA_37XX_DVFS_LOAD_1);549 ARMADA_37XX_DVFS_LOAD_1);
547 msleep(20);550 msleep(20);
551
552invalidate_l1_exp:
553 pm_cpu->l1_expiration = 0;
548}554}
549 555
550static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,556static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate,
@@ -578,7 +584,9 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, · 27 unmodified lines
578 reg = ARMADA_37XX_NB_CPU_LOAD;584 reg = ARMADA_37XX_NB_CPU_LOAD;
579 mask = ARMADA_37XX_NB_CPU_LOAD_MASK;585 mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
580 586
581 clk_pm_cpu_set_rate_wa(rate, base);587 /* Apply workaround when base CPU frequency is 1000 or 1200 MHz */
588 if (parent_rate >= 1000*1000*1000)
589 clk_pm_cpu_set_rate_wa(pm_cpu, load_level, rate, base);
582 590
583 regmap_update_bits(base, reg, mask, load_level);591 regmap_update_bits(base, reg, mask, load_level);
584 592
@@ -592,7 +600,6 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, · 7 unmodified lines
592 600
593static const struct clk_ops clk_pm_cpu_ops = {601static const struct clk_ops clk_pm_cpu_ops = {
594 .get_parent = clk_pm_cpu_get_parent,602 .get_parent = clk_pm_cpu_get_parent,
595 .set_parent = clk_pm_cpu_set_parent,
596 .round_rate = clk_pm_cpu_round_rate,603 .round_rate = clk_pm_cpu_round_rate,
597 .set_rate = clk_pm_cpu_set_rate,604 .set_rate = clk_pm_cpu_set_rate,
598 .recalc_rate = clk_pm_cpu_recalc_rate,605 .recalc_rate = clk_pm_cpu_recalc_rate,
drivers/cpufreq/Kconfig.arm+10−0
@@ -19,6 +19,16 @@ config ACPI_CPPC_CPUFREQ · 18 unmodified lines
19 19
20 If in doubt, say N.20 If in doubt, say N.
21 21
22config ACPI_CPPC_CPUFREQ_FIE
23 bool "Frequency Invariance support for CPPC cpufreq driver"
24 depends on ACPI_CPPC_CPUFREQ && GENERIC_ARCH_TOPOLOGY
25 default y
26 help
27 This extends frequency invariance support in the CPPC cpufreq driver,
28 by using CPPC delivered and reference performance counters.
29
30 If in doubt, say N.
31
22config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM32config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
23 tristate "Allwinner nvmem based SUN50I CPUFreq driver"33 tristate "Allwinner nvmem based SUN50I CPUFreq driver"
24 depends on ARCH_SUNXI34 depends on ARCH_SUNXI
drivers/cpufreq/armada-37xx-cpufreq.c+88−23
@@ -25,6 +25,10 @@ · 24 unmodified lines
25 25
26#include "cpufreq-dt.h"26#include "cpufreq-dt.h"
27 27
28/* Clk register set */
29#define ARMADA_37XX_CLK_TBG_SEL 0
30#define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF 22
31
28/* Power management in North Bridge register set */32/* Power management in North Bridge register set */
29#define ARMADA_37XX_NB_L0L1 0x1833#define ARMADA_37XX_NB_L0L1 0x18
30#define ARMADA_37XX_NB_L2L3 0x1C34#define ARMADA_37XX_NB_L2L3 0x1C
@@ -69,6 +73,8 @@ · 38 unmodified lines
69#define LOAD_LEVEL_NR 473#define LOAD_LEVEL_NR 4
70 74
71#define MIN_VOLT_MV 100075#define MIN_VOLT_MV 1000
76#define MIN_VOLT_MV_FOR_L1_1000MHZ 1108
77#define MIN_VOLT_MV_FOR_L1_1200MHZ 1155
72 78
73/* AVS value for the corresponding voltage (in mV) */79/* AVS value for the corresponding voltage (in mV) */
74static int avs_map[] = {80static int avs_map[] = {
@@ -80,6 +86,8 @@ static int avs_map[] = { · 5 unmodified lines
80};86};
81 87
82struct armada37xx_cpufreq_state {88struct armada37xx_cpufreq_state {
89 struct platform_device *pdev;
90 struct device *cpu_dev;
83 struct regmap *regmap;91 struct regmap *regmap;
84 u32 nb_l0l1;92 u32 nb_l0l1;
85 u32 nb_l2l3;93 u32 nb_l2l3;
@@ -120,10 +128,15 @@ static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) · 34 unmodified lines
120 * will be configured then the DVFS will be enabled.128 * will be configured then the DVFS will be enabled.
121 */129 */
122static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,130static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
123 struct clk *clk, u8 *divider)131 struct regmap *clk_base, u8 *divider)
124{132{
133 u32 cpu_tbg_sel;
125 int load_lvl;134 int load_lvl;
126 struct clk *parent;135
136 /* Determine to which TBG clock is CPU connected */
137 regmap_read(clk_base, ARMADA_37XX_CLK_TBG_SEL, &cpu_tbg_sel);
138 cpu_tbg_sel >>= ARMADA_37XX_CLK_TBG_SEL_CPU_OFF;
139 cpu_tbg_sel &= ARMADA_37XX_NB_TBG_SEL_MASK;
127 140
128 for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {141 for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
129 unsigned int reg, mask, val, offset = 0;142 unsigned int reg, mask, val, offset = 0;
@@ -142,6 +155,11 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, · 12 unmodified lines
142 mask = (ARMADA_37XX_NB_CLK_SEL_MASK155 mask = (ARMADA_37XX_NB_CLK_SEL_MASK
143 << ARMADA_37XX_NB_CLK_SEL_OFF);156 << ARMADA_37XX_NB_CLK_SEL_OFF);
144 157
158 /* Set TBG index, for all levels we use the same TBG */
159 val = cpu_tbg_sel << ARMADA_37XX_NB_TBG_SEL_OFF;
160 mask = (ARMADA_37XX_NB_TBG_SEL_MASK
161 << ARMADA_37XX_NB_TBG_SEL_OFF);
162
145 /*163 /*
146 * Set cpu divider based on the pre-computed array in164 * Set cpu divider based on the pre-computed array in
147 * order to have balanced step.165 * order to have balanced step.
@@ -160,14 +178,6 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, · 12 unmodified lines
160 178
161 regmap_update_bits(base, reg, mask, val);179 regmap_update_bits(base, reg, mask, val);
162 }180 }
163
164 /*
165 * Set cpu clock source, for all the level we keep the same
166 * clock source that the one already configured. For this one
167 * we need to use the clock framework
168 */
169 parent = clk_get_parent(clk);
170 clk_set_parent(clk, parent);
171}181}
172 182
173/*183/*
@@ -202,6 +212,8 @@ static u32 armada_37xx_avs_val_match(int target_vm) · 28 unmodified lines
202 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.212 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
203 * This function calculates L1 & L2 & L3 AVS values dynamically based213 * This function calculates L1 & L2 & L3 AVS values dynamically based
204 * on L0 voltage and fill all AVS values to the AVS value table.214 * on L0 voltage and fill all AVS values to the AVS value table.
215 * When base CPU frequency is 1000 or 1200 MHz then there is additional
216 * minimal avs value for load L1.
205 */217 */
206static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,218static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
207 struct armada_37xx_dvfs *dvfs)219 struct armada_37xx_dvfs *dvfs)
@@ -233,6 +245,19 @@ static void __init armada37xx_cpufreq_avs_configure(struct regmap *base, · 25 unmodified lines
233 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)245 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)
234 dvfs->avs[load_level] = avs_min;246 dvfs->avs[load_level] = avs_min;
235 247
248 /*
249 * Set the avs values for load L0 and L1 when base CPU frequency
250 * is 1000/1200 MHz to its typical initial values according to
251 * the Armada 3700 Hardware Specifications.
252 */
253 if (dvfs->cpu_freq_max >= 1000*1000*1000) {
254 if (dvfs->cpu_freq_max >= 1200*1000*1000)
255 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
256 else
257 avs_min = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
258 dvfs->avs[0] = dvfs->avs[1] = avs_min;
259 }
260
236 return;261 return;
237 }262 }
238 263
@@ -252,6 +277,26 @@ static void __init armada37xx_cpufreq_avs_configure(struct regmap *base, · 13 unmodified lines
252 target_vm = avs_map[l0_vdd_min] - 150;277 target_vm = avs_map[l0_vdd_min] - 150;
253 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;278 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);279 dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm);
280
281 /*
282 * Fix the avs value for load L1 when base CPU frequency is 1000/1200 MHz,
283 * otherwise the CPU gets stuck when switching from load L1 to load L0.
284 * Also ensure that avs value for load L1 is not higher than for L0.
285 */
286 if (dvfs->cpu_freq_max >= 1000*1000*1000) {
287 u32 avs_min_l1;
288
289 if (dvfs->cpu_freq_max >= 1200*1000*1000)
290 avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1200MHZ);
291 else
292 avs_min_l1 = armada_37xx_avs_val_match(MIN_VOLT_MV_FOR_L1_1000MHZ);
293
294 if (avs_min_l1 > dvfs->avs[0])
295 avs_min_l1 = dvfs->avs[0];
296
297 if (dvfs->avs[1] < avs_min_l1)
298 dvfs->avs[1] = avs_min_l1;
299 }
255}300}
256 301
257static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,302static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
@@ -357,12 +402,17 @@ static int __init armada37xx_cpufreq_driver_init(void) · 99 unmodified lines
357 struct armada_37xx_dvfs *dvfs;402 struct armada_37xx_dvfs *dvfs;
358 struct platform_device *pdev;403 struct platform_device *pdev;
359 unsigned long freq;404 unsigned long freq;
360 unsigned int cur_frequency, base_frequency;405 unsigned int base_frequency;
361 struct regmap *nb_pm_base, *avs_base;406 struct regmap *nb_clk_base, *nb_pm_base, *avs_base;
362 struct device *cpu_dev;407 struct device *cpu_dev;
363 int load_lvl, ret;408 int load_lvl, ret;
364 struct clk *clk, *parent;409 struct clk *clk, *parent;
365 410
411 nb_clk_base =
412 syscon_regmap_lookup_by_compatible("marvell,armada-3700-periph-clock-nb");
413 if (IS_ERR(nb_clk_base))
414 return -ENODEV;
415
366 nb_pm_base =416 nb_pm_base =
367 syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");417 syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
368 418
@@ -413,15 +463,7 @@ static int __init armada37xx_cpufreq_driver_init(void) · 44 unmodified lines
413 return -EINVAL;463 return -EINVAL;
414 }464 }
415 465
416 /* Get nominal (current) CPU frequency */466 dvfs = armada_37xx_cpu_freq_info_get(base_frequency);
417 cur_frequency = clk_get_rate(clk);
418 if (!cur_frequency) {
419 dev_err(cpu_dev, "Failed to get clock rate for CPU\n");
420 clk_put(clk);
421 return -EINVAL;
422 }
423
424 dvfs = armada_37xx_cpu_freq_info_get(cur_frequency);
425 if (!dvfs) {467 if (!dvfs) {
426 clk_put(clk);468 clk_put(clk);
427 return -EINVAL;469 return -EINVAL;
@@ -439,7 +481,7 @@ static int __init armada37xx_cpufreq_driver_init(void) · 11 unmodified lines
439 armada37xx_cpufreq_avs_configure(avs_base, dvfs);481 armada37xx_cpufreq_avs_configure(avs_base, dvfs);
440 armada37xx_cpufreq_avs_setup(avs_base, dvfs);482 armada37xx_cpufreq_avs_setup(avs_base, dvfs);
441 483
442 armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);484 armada37xx_cpufreq_dvfs_setup(nb_pm_base, nb_clk_base, dvfs->divider);
443 clk_put(clk);485 clk_put(clk);
444 486
445 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;487 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR;
@@ -466,6 +508,9 @@ static int __init armada37xx_cpufreq_driver_init(void) · 20 unmodified lines
466 if (ret)508 if (ret)
467 goto disable_dvfs;509 goto disable_dvfs;
468 510
511 armada37xx_cpufreq_state->cpu_dev = cpu_dev;
512 armada37xx_cpufreq_state->pdev = pdev;
513 platform_set_drvdata(pdev, dvfs);
469 return 0;514 return 0;
470 515
471disable_dvfs:516disable_dvfs:
@@ -473,7 +518,7 @@ disable_dvfs: · 1 unmodified line
473remove_opp:518remove_opp:
474 /* clean-up the already added opp before leaving */519 /* clean-up the already added opp before leaving */
475 while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {520 while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
476 freq = cur_frequency / dvfs->divider[load_lvl];521 freq = base_frequency / dvfs->divider[load_lvl];
477 dev_pm_opp_remove(cpu_dev, freq);522 dev_pm_opp_remove(cpu_dev, freq);
478 }523 }
479 524
@@ -484,6 +529,26 @@ remove_opp: · 4 unmodified lines
484/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */529/* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
485late_initcall(armada37xx_cpufreq_driver_init);530late_initcall(armada37xx_cpufreq_driver_init);
486 531
532static void __exit armada37xx_cpufreq_driver_exit(void)
533{
534 struct platform_device *pdev = armada37xx_cpufreq_state->pdev;
535 struct armada_37xx_dvfs *dvfs = platform_get_drvdata(pdev);
536 unsigned long freq;
537 int load_lvl;
538
539 platform_device_unregister(pdev);
540
541 armada37xx_cpufreq_disable_dvfs(armada37xx_cpufreq_state->regmap);
542
543 for (load_lvl = ARMADA_37XX_DVFS_LOAD_0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
544 freq = dvfs->cpu_freq_max / dvfs->divider[load_lvl];
545 dev_pm_opp_remove(armada37xx_cpufreq_state->cpu_dev, freq);
546 }
547
548 kfree(armada37xx_cpufreq_state);
549}
550module_exit(armada37xx_cpufreq_driver_exit);
551
487static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = {552static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = {
488 { .compatible = "marvell,armada-3700-nb-pm" },553 { .compatible = "marvell,armada-3700-nb-pm" },
489 { },554 { },
drivers/cpufreq/cppc_cpufreq.c+235−24
@@ -10,14 +10,18 @@ · 9 unmodified lines
10 10
11#define pr_fmt(fmt) "CPPC Cpufreq:" fmt11#define pr_fmt(fmt) "CPPC Cpufreq:" fmt
12 12
13#include <linux/arch_topology.h>
13#include <linux/kernel.h>14#include <linux/kernel.h>
14#include <linux/module.h>15#include <linux/module.h>
15#include <linux/delay.h>16#include <linux/delay.h>
16#include <linux/cpu.h>17#include <linux/cpu.h>
17#include <linux/cpufreq.h>18#include <linux/cpufreq.h>
18#include <linux/dmi.h>19#include <linux/dmi.h>
20#include <linux/irq_work.h>
21#include <linux/kthread.h>
19#include <linux/time.h>22#include <linux/time.h>
20#include <linux/vmalloc.h>23#include <linux/vmalloc.h>
24#include <uapi/linux/sched/types.h>
21 25
22#include <asm/unaligned.h>26#include <asm/unaligned.h>
23 27
@@ -57,6 +61,204 @@ static struct cppc_workaround_oem_info wa_info[] = { · 33 unmodified lines
57 }61 }
58};62};
59 63
64#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
65
66/* Frequency invariance support */
67struct cppc_freq_invariance {
68 int cpu;
69 struct irq_work irq_work;
70 struct kthread_work work;
71 struct cppc_perf_fb_ctrs prev_perf_fb_ctrs;
72 struct cppc_cpudata *cpu_data;
73};
74
75static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv);
76static struct kthread_worker *kworker_fie;
77static bool fie_disabled;
78
79static struct cpufreq_driver cppc_cpufreq_driver;
80static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu);
81static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
82 struct cppc_perf_fb_ctrs fb_ctrs_t0,
83 struct cppc_perf_fb_ctrs fb_ctrs_t1);
84
85/**
86 * cppc_scale_freq_workfn - CPPC arch_freq_scale updater for frequency invariance
87 * @work: The work item.
88 *
89 * The CPPC driver register itself with the topology core to provide its own
90 * implementation (cppc_scale_freq_tick()) of topology_scale_freq_tick() which
91 * gets called by the scheduler on every tick.
92 *
93 * Note that the arch specific counters have higher priority than CPPC counters,
94 * if available, though the CPPC driver doesn't need to have any special
95 * handling for that.
96 *
97 * On an invocation of cppc_scale_freq_tick(), we schedule an irq work (since we
98 * reach here from hard-irq context), which then schedules a normal work item
99 * and cppc_scale_freq_workfn() updates the per_cpu arch_freq_scale variable
100 * based on the counter updates since the last tick.
101 */
102static void cppc_scale_freq_workfn(struct kthread_work *work)
103{
104 struct cppc_freq_invariance *cppc_fi;
105 struct cppc_perf_fb_ctrs fb_ctrs = {0};
106 struct cppc_cpudata *cpu_data;
107 unsigned long local_freq_scale;
108 u64 perf;
109
110 cppc_fi = container_of(work, struct cppc_freq_invariance, work);
111 cpu_data = cppc_fi->cpu_data;
112
113 if (cppc_get_perf_ctrs(cppc_fi->cpu, &fb_ctrs)) {
114 pr_warn("%s: failed to read perf counters\n", __func__);
115 return;
116 }
117
118 cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
119 perf = cppc_perf_from_fbctrs(cpu_data, cppc_fi->prev_perf_fb_ctrs,
120 fb_ctrs);
121
122 perf <<= SCHED_CAPACITY_SHIFT;
123 local_freq_scale = div64_u64(perf, cpu_data->perf_caps.highest_perf);
124 if (WARN_ON(local_freq_scale > 1024))
125 local_freq_scale = 1024;
126
127 per_cpu(arch_freq_scale, cppc_fi->cpu) = local_freq_scale;
128}
129
130static void cppc_irq_work(struct irq_work *irq_work)
131{
132 struct cppc_freq_invariance *cppc_fi;
133
134 cppc_fi = container_of(irq_work, struct cppc_freq_invariance, irq_work);
135 kthread_queue_work(kworker_fie, &cppc_fi->work);
136}
137
138static void cppc_scale_freq_tick(void)
139{
140 struct cppc_freq_invariance *cppc_fi = &per_cpu(cppc_freq_inv, smp_processor_id());
141
142 /*
143 * cppc_get_perf_ctrs() can potentially sleep, call that from the right
144 * context.
145 */
146 irq_work_queue(&cppc_fi->irq_work);
147}
148
149static struct scale_freq_data cppc_sftd = {
150 .source = SCALE_FREQ_SOURCE_CPPC,
151 .set_freq_scale = cppc_scale_freq_tick,
152};
153
154static void cppc_freq_invariance_policy_init(struct cpufreq_policy *policy,
155 struct cppc_cpudata *cpu_data)
156{
157 struct cppc_perf_fb_ctrs fb_ctrs = {0};
158 struct cppc_freq_invariance *cppc_fi;
159 int i, ret;
160
161 if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
162 return;
163
164 if (fie_disabled)
165 return;
166
167 for_each_cpu(i, policy->cpus) {
168 cppc_fi = &per_cpu(cppc_freq_inv, i);
169 cppc_fi->cpu = i;
170 cppc_fi->cpu_data = cpu_data;
171 kthread_init_work(&cppc_fi->work, cppc_scale_freq_workfn);
172 init_irq_work(&cppc_fi->irq_work, cppc_irq_work);
173
174 ret = cppc_get_perf_ctrs(i, &fb_ctrs);
175 if (ret) {
176 pr_warn("%s: failed to read perf counters: %d\n",
177 __func__, ret);
178 fie_disabled = true;
179 } else {
180 cppc_fi->prev_perf_fb_ctrs = fb_ctrs;
181 }
182 }
183}
184
185static void __init cppc_freq_invariance_init(void)
186{
187 struct sched_attr attr = {
188 .size = sizeof(struct sched_attr),
189 .sched_policy = SCHED_DEADLINE,
190 .sched_nice = 0,
191 .sched_priority = 0,
192 /*
193 * Fake (unused) bandwidth; workaround to "fix"
194 * priority inheritance.
195 */
196 .sched_runtime = 1000000,
197 .sched_deadline = 10000000,
198 .sched_period = 10000000,
199 };
200 int ret;
201
202 if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
203 return;
204
205 if (fie_disabled)
206 return;
207
208 kworker_fie = kthread_create_worker(0, "cppc_fie");
209 if (IS_ERR(kworker_fie))
210 return;
211
212 ret = sched_setattr_nocheck(kworker_fie->task, &attr);
213 if (ret) {
214 pr_warn("%s: failed to set SCHED_DEADLINE: %d\n", __func__,
215 ret);
216 kthread_destroy_worker(kworker_fie);
217 return;
218 }
219
220 /* Register for freq-invariance */
221 topology_set_scale_freq_source(&cppc_sftd, cpu_present_mask);
222}
223
224static void cppc_freq_invariance_exit(void)
225{
226 struct cppc_freq_invariance *cppc_fi;
227 int i;
228
229 if (cppc_cpufreq_driver.get == hisi_cppc_cpufreq_get_rate)
230 return;
231
232 if (fie_disabled)
233 return;
234
235 topology_clear_scale_freq_source(SCALE_FREQ_SOURCE_CPPC, cpu_present_mask);
236
237 for_each_possible_cpu(i) {
238 cppc_fi = &per_cpu(cppc_freq_inv, i);
239 irq_work_sync(&cppc_fi->irq_work);
240 }
241
242 kthread_destroy_worker(kworker_fie);
243 kworker_fie = NULL;
244}
245
246#else
247static inline void
248cppc_freq_invariance_policy_init(struct cpufreq_policy *policy,
249 struct cppc_cpudata *cpu_data)
250{
251}
252
253static inline void cppc_freq_invariance_init(void)
254{
255}
256
257static inline void cppc_freq_invariance_exit(void)
258{
259}
260#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */
261
60/* Callback function used to retrieve the max frequency from DMI */262/* Callback function used to retrieve the max frequency from DMI */
61static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)263static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
62{264{
@@ -216,26 +418,16 @@ static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) · 153 unmodified lines
216{418{
217 unsigned long implementor = read_cpuid_implementor();419 unsigned long implementor = read_cpuid_implementor();
218 unsigned long part_num = read_cpuid_part_number();420 unsigned long part_num = read_cpuid_part_number();
219 unsigned int delay_us = 0;
220 421
221 switch (implementor) {422 switch (implementor) {
222 case ARM_CPU_IMP_QCOM:423 case ARM_CPU_IMP_QCOM:
223 switch (part_num) {424 switch (part_num) {
224 case QCOM_CPU_PART_FALKOR_V1:425 case QCOM_CPU_PART_FALKOR_V1:
225 case QCOM_CPU_PART_FALKOR:426 case QCOM_CPU_PART_FALKOR:
226 delay_us = 10000;427 return 10000;
227 break;
228 default:
229 delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
230 break;
231 }428 }
232 break;
233 default:
234 delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
235 break;
236 }429 }
237 430 return cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
238 return delay_us;
239}431}
240 432
241#else433#else
@@ -355,9 +547,12 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) · 113 unmodified lines
355 cpu_data->perf_ctrls.desired_perf = caps->highest_perf;547 cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
356 548
357 ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);549 ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
358 if (ret)550 if (ret) {
359 pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",551 pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
360 caps->highest_perf, cpu, ret);552 caps->highest_perf, cpu, ret);
553 } else {
554 cppc_freq_invariance_policy_init(policy, cpu_data);
555 }
361 556
362 return ret;557 return ret;
363}558}
@@ -370,12 +565,12 @@ static inline u64 get_delta(u64 t1, u64 t0) · 6 unmodified lines
370 return (u32)t1 - (u32)t0;565 return (u32)t1 - (u32)t0;
371}566}
372 567
373static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data,568static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
374 struct cppc_perf_fb_ctrs fb_ctrs_t0,569 struct cppc_perf_fb_ctrs fb_ctrs_t0,
375 struct cppc_perf_fb_ctrs fb_ctrs_t1)570 struct cppc_perf_fb_ctrs fb_ctrs_t1)
376{571{
377 u64 delta_reference, delta_delivered;572 u64 delta_reference, delta_delivered;
378 u64 reference_perf, delivered_perf;573 u64 reference_perf;
379 574
380 reference_perf = fb_ctrs_t0.reference_perf;575 reference_perf = fb_ctrs_t0.reference_perf;
381 576
@@ -384,12 +579,21 @@ static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data, · 2 unmodified lines
384 delta_delivered = get_delta(fb_ctrs_t1.delivered,579 delta_delivered = get_delta(fb_ctrs_t1.delivered,
385 fb_ctrs_t0.delivered);580 fb_ctrs_t0.delivered);
386 581
387 /* Check to avoid divide-by zero */582 /* Check to avoid divide-by zero and invalid delivered_perf */
388 if (delta_reference || delta_delivered)583 if (!delta_reference || !delta_delivered)
389 delivered_perf = (reference_perf * delta_delivered) /584 return cpu_data->perf_ctrls.desired_perf;
390 delta_reference;585
391 else586 return (reference_perf * delta_delivered) / delta_reference;
392 delivered_perf = cpu_data->perf_ctrls.desired_perf;587}
588
589static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data,
590 struct cppc_perf_fb_ctrs fb_ctrs_t0,
591 struct cppc_perf_fb_ctrs fb_ctrs_t1)
592{
593 u64 delivered_perf;
594
595 delivered_perf = cppc_perf_from_fbctrs(cpu_data, fb_ctrs_t0,
596 fb_ctrs_t1);
393 597
394 return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);598 return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
395}599}
@@ -514,6 +718,8 @@ static void cppc_check_hisi_workaround(void) · 118 unmodified lines
514 718
515static int __init cppc_cpufreq_init(void)719static int __init cppc_cpufreq_init(void)
516{720{
721 int ret;
722
517 if ((acpi_disabled) || !acpi_cpc_valid())723 if ((acpi_disabled) || !acpi_cpc_valid())
518 return -ENODEV;724 return -ENODEV;
519 725
@@ -521,7 +727,11 @@ static int __init cppc_cpufreq_init(void) · 1 unmodified line
521 727
522 cppc_check_hisi_workaround();728 cppc_check_hisi_workaround();
523 729
524 return cpufreq_register_driver(&cppc_cpufreq_driver);730 ret = cpufreq_register_driver(&cppc_cpufreq_driver);
731 if (!ret)
732 cppc_freq_invariance_init();
733
734 return ret;
525}735}
526 736
527static inline void free_cpu_data(void)737static inline void free_cpu_data(void)
@@ -538,6 +748,7 @@ static inline void free_cpu_data(void) · 10 unmodified lines
538 748
539static void __exit cppc_cpufreq_exit(void)749static void __exit cppc_cpufreq_exit(void)
540{750{
751 cppc_freq_invariance_exit();
541 cpufreq_unregister_driver(&cppc_cpufreq_driver);752 cpufreq_unregister_driver(&cppc_cpufreq_driver);
542 753
543 free_cpu_data();754 free_cpu_data();
drivers/cpufreq/cpufreq-dt.c+7−2
@@ -255,10 +255,15 @@ static int dt_cpufreq_early_init(struct device *dev, int cpu) · 254 unmodified lines
255 * before updating priv->cpus. Otherwise, we will end up creating255 * before updating priv->cpus. Otherwise, we will end up creating
256 * duplicate OPPs for the CPUs.256 * duplicate OPPs for the CPUs.
257 *257 *
258 * OPPs might be populated at runtime, don't check for error here.258 * OPPs might be populated at runtime, don't fail for error here unless
259 * it is -EPROBE_DEFER.
259 */260 */
260 if (!dev_pm_opp_of_cpumask_add_table(priv->cpus))261 ret = dev_pm_opp_of_cpumask_add_table(priv->cpus);
262 if (!ret) {
261 priv->have_static_opps = true;263 priv->have_static_opps = true;
264 } else if (ret == -EPROBE_DEFER) {
265 goto out;
266 }
262 267
263 /*268 /*
264 * The OPP table must be initialized, statically or dynamically, by this269 * The OPP table must be initialized, statically or dynamically, by this
drivers/cpufreq/s5pv210-cpufreq.c+7−7
@@ -91,7 +91,7 @@ static DEFINE_MUTEX(set_freq_lock); · 90 unmodified lines
91/* Use 800MHz when entering sleep mode */91/* Use 800MHz when entering sleep mode */
92#define SLEEP_FREQ (800 * 1000)92#define SLEEP_FREQ (800 * 1000)
93 93
94/* Tracks if cpu freqency can be updated anymore */94/* Tracks if CPU frequency can be updated anymore */
95static bool no_cpufreq_access;95static bool no_cpufreq_access;
96 96
97/*97/*
@@ -190,7 +190,7 @@ static u32 clkdiv_val[5][11] = { · 92 unmodified lines
190 190
191/*191/*
192 * This function set DRAM refresh counter192 * This function set DRAM refresh counter
193 * accoriding to operating frequency of DRAM193 * according to operating frequency of DRAM
194 * ch: DMC port number 0 or 1194 * ch: DMC port number 0 or 1
195 * freq: Operating frequency of DRAM(KHz)195 * freq: Operating frequency of DRAM(KHz)
196 */196 */
@@ -320,7 +320,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 123 unmodified lines
320 320
321 /*321 /*
322 * 3. DMC1 refresh count for 133Mhz if (index == L4) is322 * 3. DMC1 refresh count for 133Mhz if (index == L4) is
323 * true refresh counter is already programed in upper323 * true refresh counter is already programmed in upper
324 * code. 0x287@83Mhz324 * code. 0x287@83Mhz
325 */325 */
326 if (!bus_speed_changing)326 if (!bus_speed_changing)
@@ -378,7 +378,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 51 unmodified lines
378 /*378 /*
379 * 6. Turn on APLL379 * 6. Turn on APLL
380 * 6-1. Set PMS values380 * 6-1. Set PMS values
381 * 6-2. Wait untile the PLL is locked381 * 6-2. Wait until the PLL is locked
382 */382 */
383 if (index == L0)383 if (index == L0)
384 writel_relaxed(APLL_VAL_1000, S5P_APLL_CON);384 writel_relaxed(APLL_VAL_1000, S5P_APLL_CON);
@@ -390,7 +390,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 5 unmodified lines
390 } while (!(reg & (0x1 << 29)));390 } while (!(reg & (0x1 << 29)));
391 391
392 /*392 /*
393 * 7. Change souce clock from SCLKMPLL(667Mhz)393 * 7. Change source clock from SCLKMPLL(667Mhz)
394 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX394 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
395 * (667/4=166)->(200/4=50)Mhz395 * (667/4=166)->(200/4=50)Mhz
396 */396 */
@@ -439,8 +439,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 42 unmodified lines
439 }439 }
440 440
441 /*441 /*
442 * L4 level need to change memory bus speed, hence onedram clock divier442 * L4 level needs to change memory bus speed, hence ONEDRAM clock
443 * and memory refresh parameter should be changed443 * divider and memory refresh parameter should be changed
444 */444 */
445 if (bus_speed_changing) {445 if (bus_speed_changing) {
446 reg = readl_relaxed(S5P_CLK_DIV6);446 reg = readl_relaxed(S5P_CLK_DIV6);
include/linux/arch_topology.h+16−3
@@ -23,18 +23,31 @@ static inline unsigned long topology_get_cpu_scale(int cpu) · 22 unmodified lines
23 23
24void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity);24void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity);
25 25
26DECLARE_PER_CPU(unsigned long, freq_scale);26DECLARE_PER_CPU(unsigned long, arch_freq_scale);
27 27
28static inline unsigned long topology_get_freq_scale(int cpu)28static inline unsigned long topology_get_freq_scale(int cpu)
29{29{
30 return per_cpu(freq_scale, cpu);30 return per_cpu(arch_freq_scale, cpu);
31}31}
32 32
33void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,33void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,
34 unsigned long max_freq);34 unsigned long max_freq);
35bool topology_scale_freq_invariant(void);35bool topology_scale_freq_invariant(void);
36 36
37bool arch_freq_counters_available(const struct cpumask *cpus);37enum scale_freq_source {
38 SCALE_FREQ_SOURCE_CPUFREQ = 0,
39 SCALE_FREQ_SOURCE_ARCH,
40 SCALE_FREQ_SOURCE_CPPC,
41};
42
43struct scale_freq_data {
44 enum scale_freq_source source;
45 void (*set_freq_scale)(void);
46};
47
48void topology_scale_freq_tick(void);
49void topology_set_scale_freq_source(struct scale_freq_data *data, const struct cpumask *cpus);
50void topology_clear_scale_freq_source(enum scale_freq_source source, const struct cpumask *cpus);
38 51
39DECLARE_PER_CPU(unsigned long, thermal_pressure);52DECLARE_PER_CPU(unsigned long, thermal_pressure);
40 53
kernel/sched/core.c+1−0
@@ -6384,6 +6384,7 @@ int sched_setattr_nocheck(struct task_struct *p, const struct sched_attr *attr) · 6383 unmodified lines
6384{6384{
6385 return __sched_setscheduler(p, attr, false, true);6385 return __sched_setscheduler(p, attr, false, true);
6386}6386}
6387EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
6387 6388
6388/**6389/**
6389 * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.6390 * sched_setscheduler_nocheck - change the scheduling policy and/or RT priority of a thread from kernelspace.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t