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
1717 #include <linux/arch_topology.h>
1818
1919 void update_freq_counters_refs(void);
20−void 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 */
2920
3021 /* Replace task scheduler's default frequency-invariant accounting */
22+#define arch_scale_freq_tick topology_scale_freq_tick
3123 #define arch_set_freq_scale topology_set_freq_scale
3224 #define arch_scale_freq_capacity topology_get_freq_scale
3325 #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
199199 return 0;
200200 }
201201
202−static DEFINE_STATIC_KEY_FALSE(amu_fie_key);
203−#define amu_freq_invariant() static_branch_unlikely(&amu_fie_key)
202+static void amu_scale_freq_tick(void)
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+
236+static struct scale_freq_data amu_sfd = {
237+ .source = SCALE_FREQ_SOURCE_ARCH,
238+ .set_freq_scale = amu_scale_freq_tick,
239+};
204240
205241 static void amu_fie_setup(const struct cpumask *cpus)
206242 {
207− bool invariant;
208243 int cpu;
209244
210245 /* 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
221256
222257 cpumask_or(amu_fie_cpus, amu_fie_cpus, cpus);
223258
224− invariant = topology_scale_freq_invariant();
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);
259+ topology_set_scale_freq_source(&amu_sfd, amu_fie_cpus);
231260
232261 pr_debug("CPUs[%*pbl]: counters will be used for FIE.",
233262 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();
243263 }
244264
245265 static 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
256276 * initialized AMU support and enabled invariance. The AMU counters will
257277 * keep on working just fine in the absence of the cpufreq driver, and
258278 * 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 those
260− * CPUs are running at.
279+ * value of arch_freq_scale will remain valid as that is the frequency
280+ * those CPUs are running at.
261281 */
262282
263283 return 0;
@@ -283,53 +303,6 @@ static int __init init_amu_fie(void) · 19 unmodified lines
283303 }
284304 core_initcall(init_amu_fie);
285305
286−bool arch_freq_counters_available(const struct cpumask *cpus)
287−{
288− return amu_freq_invariant() &&
289− cpumask_subset(cpus, amu_fie_cpus);
290−}
291−
292−void 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−
333306 #ifdef CONFIG_ACPI_CPPC_LIB
334307 #include <acpi/cppc_acpi.h>
335308
drivers/base/arch_topology.c+83−6
@@ -21,17 +21,94 @@ · 20 unmodified lines
2121 #include <linux/sched.h>
2222 #include <linux/smp.h>
2323
24+static DEFINE_PER_CPU(struct scale_freq_data *, sft_data);
25+static struct cpumask scale_freq_counters_mask;
26+static bool scale_freq_invariant;
27+
28+static bool supports_scale_freq_counters(const struct cpumask *cpus)
29+{
30+ return cpumask_subset(cpus, &scale_freq_counters_mask);
31+}
32+
2433 bool topology_scale_freq_invariant(void)
2534 {
2635 return cpufreq_supports_freq_invariance() ||
27− arch_freq_counters_available(cpu_online_mask);
36+ supports_scale_freq_counters(cpu_online_mask);
2837 }
2938
30−__weak bool arch_freq_counters_available(const struct cpumask *cpus)
39+static void update_scale_freq_invariant(bool status)
3140 {
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+ }
3354 }
34−DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
55+
56+void 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+}
81+EXPORT_SYMBOL_GPL(topology_set_scale_freq_source);
82+
83+void 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+}
100+EXPORT_SYMBOL_GPL(topology_clear_scale_freq_source);
101+
102+void 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+
110+DEFINE_PER_CPU(unsigned long, arch_freq_scale) = SCHED_CAPACITY_SCALE;
111+EXPORT_PER_CPU_SYMBOL_GPL(arch_freq_scale);
35112
36113 void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,
37114 unsigned long max_freq)
@@ -47,13 +124,13 @@ void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq, · 9 unmodified lines
47124 * want to update the scale factor with information from CPUFREQ.
48125 * Instead the scale factor will be updated from arch_scale_freq_tick.
49126 */
50− if (arch_freq_counters_available(cpus))
127+ if (supports_scale_freq_counters(cpus))
51128 return;
52129
53130 scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq;
54131
55132 for_each_cpu(i, cpus)
56− per_cpu(freq_scale, i) = scale;
133+ per_cpu(arch_freq_scale, i) = scale;
57134 }
58135
59136 DEFINE_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
8484 void __iomem *reg_div;
8585 u8 shift_div;
8686 struct regmap *nb_pm_base;
87+ unsigned long l1_expiration;
8788 };
8889
8990 #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
440441 return val;
441442 }
442443
443−static 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−
470444 static unsigned long clk_pm_cpu_recalc_rate(struct clk_hw *hw,
471445 unsigned long parent_rate)
472446 {
@@ -514,8 +488,10 @@ static long clk_pm_cpu_round_rate(struct clk_hw *hw, unsigned long rate, · 41 unmodified lines
514488 }
515489
516490 /*
517− * Switching the CPU from the L2 or L3 frequencies (300 and 200 Mhz
518− * respectively) to L0 frequency (1.2 Ghz) requires a significant
491+ * Workaround when base CPU frequnecy is 1000 or 1200 MHz
492+ *
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
519495 * amount of time to let VDD stabilize to the appropriate
520496 * voltage. This amount of time is large enough that it cannot be
521497 * 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
525501 * To work around this problem, we prevent switching directly from the
526502 * L2/L3 frequencies to the L0 frequency, and instead switch to the L1
527503 * 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)
529505 * 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).
531507 */
532−static void clk_pm_cpu_set_rate_wa(unsigned long rate, struct regmap *base)
508+static 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)
533511 {
534512 unsigned int cur_level;
535513
536− if (rate != 1200 * 1000 * 1000)
537− return;
538−
539514 regmap_read(base, ARMADA_37XX_NB_CPU_LOAD, &cur_level);
540515 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);
542530 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;
543546
544547 regmap_update_bits(base, ARMADA_37XX_NB_CPU_LOAD,
545548 ARMADA_37XX_NB_CPU_LOAD_MASK,
546549 ARMADA_37XX_DVFS_LOAD_1);
547550 msleep(20);
551+
552+invalidate_l1_exp:
553+ pm_cpu->l1_expiration = 0;
548554 }
549555
550556 static 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
578584 reg = ARMADA_37XX_NB_CPU_LOAD;
579585 mask = ARMADA_37XX_NB_CPU_LOAD_MASK;
580586
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);
582590
583591 regmap_update_bits(base, reg, mask, load_level);
584592
@@ -592,7 +600,6 @@ static int clk_pm_cpu_set_rate(struct clk_hw *hw, unsigned long rate, · 7 unmodified lines
592600
593601 static const struct clk_ops clk_pm_cpu_ops = {
594602 .get_parent = clk_pm_cpu_get_parent,
595− .set_parent = clk_pm_cpu_set_parent,
596603 .round_rate = clk_pm_cpu_round_rate,
597604 .set_rate = clk_pm_cpu_set_rate,
598605 .recalc_rate = clk_pm_cpu_recalc_rate,
drivers/cpufreq/Kconfig.arm+10−0
@@ -19,6 +19,16 @@ config ACPI_CPPC_CPUFREQ · 18 unmodified lines
1919
2020 If in doubt, say N.
2121
22+config 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+
2232 config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM
2333 tristate "Allwinner nvmem based SUN50I CPUFreq driver"
2434 depends on ARCH_SUNXI
drivers/cpufreq/armada-37xx-cpufreq.c+88−23
@@ -25,6 +25,10 @@ · 24 unmodified lines
2525
2626 #include "cpufreq-dt.h"
2727
28+/* Clk register set */
29+#define ARMADA_37XX_CLK_TBG_SEL 0
30+#define ARMADA_37XX_CLK_TBG_SEL_CPU_OFF 22
31+
2832 /* Power management in North Bridge register set */
2933 #define ARMADA_37XX_NB_L0L1 0x18
3034 #define ARMADA_37XX_NB_L2L3 0x1C
@@ -69,6 +73,8 @@ · 38 unmodified lines
6973 #define LOAD_LEVEL_NR 4
7074
7175 #define MIN_VOLT_MV 1000
76+#define MIN_VOLT_MV_FOR_L1_1000MHZ 1108
77+#define MIN_VOLT_MV_FOR_L1_1200MHZ 1155
7278
7379 /* AVS value for the corresponding voltage (in mV) */
7480 static int avs_map[] = {
@@ -80,6 +86,8 @@ static int avs_map[] = { · 5 unmodified lines
8086 };
8187
8288 struct armada37xx_cpufreq_state {
89+ struct platform_device *pdev;
90+ struct device *cpu_dev;
8391 struct regmap *regmap;
8492 u32 nb_l0l1;
8593 u32 nb_l2l3;
@@ -120,10 +128,15 @@ static struct armada_37xx_dvfs *armada_37xx_cpu_freq_info_get(u32 freq) · 34 unmodified lines
120128 * will be configured then the DVFS will be enabled.
121129 */
122130 static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base,
123− struct clk *clk, u8 *divider)
131+ struct regmap *clk_base, u8 *divider)
124132 {
133+ u32 cpu_tbg_sel;
125134 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;
127140
128141 for (load_lvl = 0; load_lvl < LOAD_LEVEL_NR; load_lvl++) {
129142 unsigned int reg, mask, val, offset = 0;
@@ -142,6 +155,11 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, · 12 unmodified lines
142155 mask = (ARMADA_37XX_NB_CLK_SEL_MASK
143156 << ARMADA_37XX_NB_CLK_SEL_OFF);
144157
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+
145163 /*
146164 * Set cpu divider based on the pre-computed array in
147165 * order to have balanced step.
@@ -160,14 +178,6 @@ static void __init armada37xx_cpufreq_dvfs_setup(struct regmap *base, · 12 unmodified lines
160178
161179 regmap_update_bits(base, reg, mask, val);
162180 }
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);
171181 }
172182
173183 /*
@@ -202,6 +212,8 @@ static u32 armada_37xx_avs_val_match(int target_vm) · 28 unmodified lines
202212 * - L2 & L3 voltage should be about 150mv smaller than L0 voltage.
203213 * This function calculates L1 & L2 & L3 AVS values dynamically based
204214 * 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.
205217 */
206218 static void __init armada37xx_cpufreq_avs_configure(struct regmap *base,
207219 struct armada_37xx_dvfs *dvfs)
@@ -233,6 +245,19 @@ static void __init armada37xx_cpufreq_avs_configure(struct regmap *base, · 25 unmodified lines
233245 for (load_level = 1; load_level < LOAD_LEVEL_NR; load_level++)
234246 dvfs->avs[load_level] = avs_min;
235247
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+
236261 return;
237262 }
238263
@@ -252,6 +277,26 @@ static void __init armada37xx_cpufreq_avs_configure(struct regmap *base, · 13 unmodified lines
252277 target_vm = avs_map[l0_vdd_min] - 150;
253278 target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV;
254279 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+ }
255300 }
256301
257302 static void __init armada37xx_cpufreq_avs_setup(struct regmap *base,
@@ -357,12 +402,17 @@ static int __init armada37xx_cpufreq_driver_init(void) · 99 unmodified lines
357402 struct armada_37xx_dvfs *dvfs;
358403 struct platform_device *pdev;
359404 unsigned long freq;
360− unsigned int cur_frequency, base_frequency;
361− struct regmap *nb_pm_base, *avs_base;
405+ unsigned int base_frequency;
406+ struct regmap *nb_clk_base, *nb_pm_base, *avs_base;
362407 struct device *cpu_dev;
363408 int load_lvl, ret;
364409 struct clk *clk, *parent;
365410
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+
366416 nb_pm_base =
367417 syscon_regmap_lookup_by_compatible("marvell,armada-3700-nb-pm");
368418
@@ -413,15 +463,7 @@ static int __init armada37xx_cpufreq_driver_init(void) · 44 unmodified lines
413463 return -EINVAL;
414464 }
415465
416− /* Get nominal (current) CPU 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);
466+ dvfs = armada_37xx_cpu_freq_info_get(base_frequency);
425467 if (!dvfs) {
426468 clk_put(clk);
427469 return -EINVAL;
@@ -439,7 +481,7 @@ static int __init armada37xx_cpufreq_driver_init(void) · 11 unmodified lines
439481 armada37xx_cpufreq_avs_configure(avs_base, dvfs);
440482 armada37xx_cpufreq_avs_setup(avs_base, dvfs);
441483
442− armada37xx_cpufreq_dvfs_setup(nb_pm_base, clk, dvfs->divider);
484+ armada37xx_cpufreq_dvfs_setup(nb_pm_base, nb_clk_base, dvfs->divider);
443485 clk_put(clk);
444486
445487 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
466508 if (ret)
467509 goto disable_dvfs;
468510
511+ armada37xx_cpufreq_state->cpu_dev = cpu_dev;
512+ armada37xx_cpufreq_state->pdev = pdev;
513+ platform_set_drvdata(pdev, dvfs);
469514 return 0;
470515
471516 disable_dvfs:
@@ -473,7 +518,7 @@ disable_dvfs: · 1 unmodified line
473518 remove_opp:
474519 /* clean-up the already added opp before leaving */
475520 while (load_lvl-- > ARMADA_37XX_DVFS_LOAD_0) {
476− freq = cur_frequency / dvfs->divider[load_lvl];
521+ freq = base_frequency / dvfs->divider[load_lvl];
477522 dev_pm_opp_remove(cpu_dev, freq);
478523 }
479524
@@ -484,6 +529,26 @@ remove_opp: · 4 unmodified lines
484529 /* late_initcall, to guarantee the driver is loaded after A37xx clock driver */
485530 late_initcall(armada37xx_cpufreq_driver_init);
486531
532+static 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+}
550+module_exit(armada37xx_cpufreq_driver_exit);
551+
487552 static const struct of_device_id __maybe_unused armada37xx_cpufreq_of_match[] = {
488553 { .compatible = "marvell,armada-3700-nb-pm" },
489554 { },
drivers/cpufreq/cppc_cpufreq.c+235−24
@@ -10,14 +10,18 @@ · 9 unmodified lines
1010
1111 #define pr_fmt(fmt) "CPPC Cpufreq:" fmt
1212
13+#include <linux/arch_topology.h>
1314 #include <linux/kernel.h>
1415 #include <linux/module.h>
1516 #include <linux/delay.h>
1617 #include <linux/cpu.h>
1718 #include <linux/cpufreq.h>
1819 #include <linux/dmi.h>
20+#include <linux/irq_work.h>
21+#include <linux/kthread.h>
1922 #include <linux/time.h>
2023 #include <linux/vmalloc.h>
24+#include <uapi/linux/sched/types.h>
2125
2226 #include <asm/unaligned.h>
2327
@@ -57,6 +61,204 @@ static struct cppc_workaround_oem_info wa_info[] = { · 33 unmodified lines
5761 }
5862 };
5963
64+#ifdef CONFIG_ACPI_CPPC_CPUFREQ_FIE
65+
66+/* Frequency invariance support */
67+struct 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+
75+static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv);
76+static struct kthread_worker *kworker_fie;
77+static bool fie_disabled;
78+
79+static struct cpufreq_driver cppc_cpufreq_driver;
80+static unsigned int hisi_cppc_cpufreq_get_rate(unsigned int cpu);
81+static 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+ */
102+static 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+
130+static 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+
138+static 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+
149+static struct scale_freq_data cppc_sftd = {
150+ .source = SCALE_FREQ_SOURCE_CPPC,
151+ .set_freq_scale = cppc_scale_freq_tick,
152+};
153+
154+static 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+
185+static 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+
224+static 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
247+static inline void
248+cppc_freq_invariance_policy_init(struct cpufreq_policy *policy,
249+ struct cppc_cpudata *cpu_data)
250+{
251+}
252+
253+static inline void cppc_freq_invariance_init(void)
254+{
255+}
256+
257+static inline void cppc_freq_invariance_exit(void)
258+{
259+}
260+#endif /* CONFIG_ACPI_CPPC_CPUFREQ_FIE */
261+
60262 /* Callback function used to retrieve the max frequency from DMI */
61263 static void cppc_find_dmi_mhz(const struct dmi_header *dm, void *private)
62264 {
@@ -216,26 +418,16 @@ static unsigned int cppc_cpufreq_get_transition_delay_us(unsigned int cpu) · 153 unmodified lines
216418 {
217419 unsigned long implementor = read_cpuid_implementor();
218420 unsigned long part_num = read_cpuid_part_number();
219− unsigned int delay_us = 0;
220421
221422 switch (implementor) {
222423 case ARM_CPU_IMP_QCOM:
223424 switch (part_num) {
224425 case QCOM_CPU_PART_FALKOR_V1:
225426 case QCOM_CPU_PART_FALKOR:
226− delay_us = 10000;
227− break;
228− default:
229− delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
230− break;
427+ return 10000;
231428 }
232− break;
233− default:
234− delay_us = cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
235− break;
236429 }
237−
238− return delay_us;
430+ return cppc_get_transition_latency(cpu) / NSEC_PER_USEC;
239431 }
240432
241433 #else
@@ -355,9 +547,12 @@ static int cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) · 113 unmodified lines
355547 cpu_data->perf_ctrls.desired_perf = caps->highest_perf;
356548
357549 ret = cppc_set_perf(cpu, &cpu_data->perf_ctrls);
358− if (ret)
550+ if (ret) {
359551 pr_debug("Err setting perf value:%d on CPU:%d. ret:%d\n",
360552 caps->highest_perf, cpu, ret);
553+ } else {
554+ cppc_freq_invariance_policy_init(policy, cpu_data);
555+ }
361556
362557 return ret;
363558 }
@@ -370,12 +565,12 @@ static inline u64 get_delta(u64 t1, u64 t0) · 6 unmodified lines
370565 return (u32)t1 - (u32)t0;
371566 }
372567
373−static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data,
374− struct cppc_perf_fb_ctrs fb_ctrs_t0,
375− struct cppc_perf_fb_ctrs fb_ctrs_t1)
568+static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data,
569+ struct cppc_perf_fb_ctrs fb_ctrs_t0,
570+ struct cppc_perf_fb_ctrs fb_ctrs_t1)
376571 {
377572 u64 delta_reference, delta_delivered;
378− u64 reference_perf, delivered_perf;
573+ u64 reference_perf;
379574
380575 reference_perf = fb_ctrs_t0.reference_perf;
381576
@@ -384,12 +579,21 @@ static int cppc_get_rate_from_fbctrs(struct cppc_cpudata *cpu_data, · 2 unmodified lines
384579 delta_delivered = get_delta(fb_ctrs_t1.delivered,
385580 fb_ctrs_t0.delivered);
386581
387− /* Check to avoid divide-by zero */
388− if (delta_reference || delta_delivered)
389− delivered_perf = (reference_perf * delta_delivered) /
390− delta_reference;
391− else
392− delivered_perf = cpu_data->perf_ctrls.desired_perf;
582+ /* Check to avoid divide-by zero and invalid delivered_perf */
583+ if (!delta_reference || !delta_delivered)
584+ return cpu_data->perf_ctrls.desired_perf;
585+
586+ return (reference_perf * delta_delivered) / delta_reference;
587+}
588+
589+static 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);
393597
394598 return cppc_cpufreq_perf_to_khz(cpu_data, delivered_perf);
395599 }
@@ -514,6 +718,8 @@ static void cppc_check_hisi_workaround(void) · 118 unmodified lines
514718
515719 static int __init cppc_cpufreq_init(void)
516720 {
721+ int ret;
722+
517723 if ((acpi_disabled) || !acpi_cpc_valid())
518724 return -ENODEV;
519725
@@ -521,7 +727,11 @@ static int __init cppc_cpufreq_init(void) · 1 unmodified line
521727
522728 cppc_check_hisi_workaround();
523729
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;
525735 }
526736
527737 static inline void free_cpu_data(void)
@@ -538,6 +748,7 @@ static inline void free_cpu_data(void) · 10 unmodified lines
538748
539749 static void __exit cppc_cpufreq_exit(void)
540750 {
751+ cppc_freq_invariance_exit();
541752 cpufreq_unregister_driver(&cppc_cpufreq_driver);
542753
543754 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
255255 * before updating priv->cpus. Otherwise, we will end up creating
256256 * duplicate OPPs for the CPUs.
257257 *
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.
259260 */
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) {
261263 priv->have_static_opps = true;
264+ } else if (ret == -EPROBE_DEFER) {
265+ goto out;
266+ }
262267
263268 /*
264269 * 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
9191 /* Use 800MHz when entering sleep mode */
9292 #define SLEEP_FREQ (800 * 1000)
9393
94−/* Tracks if cpu freqency can be updated anymore */
94+/* Tracks if CPU frequency can be updated anymore */
9595 static bool no_cpufreq_access;
9696
9797 /*
@@ -190,7 +190,7 @@ static u32 clkdiv_val[5][11] = { · 92 unmodified lines
190190
191191 /*
192192 * This function set DRAM refresh counter
193− * accoriding to operating frequency of DRAM
193+ * according to operating frequency of DRAM
194194 * ch: DMC port number 0 or 1
195195 * freq: Operating frequency of DRAM(KHz)
196196 */
@@ -320,7 +320,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 123 unmodified lines
320320
321321 /*
322322 * 3. DMC1 refresh count for 133Mhz if (index == L4) is
323− * true refresh counter is already programed in upper
323+ * true refresh counter is already programmed in upper
324324 * code. 0x287@83Mhz
325325 */
326326 if (!bus_speed_changing)
@@ -378,7 +378,7 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 51 unmodified lines
378378 /*
379379 * 6. Turn on APLL
380380 * 6-1. Set PMS values
381− * 6-2. Wait untile the PLL is locked
381+ * 6-2. Wait until the PLL is locked
382382 */
383383 if (index == L0)
384384 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
390390 } while (!(reg & (0x1 << 29)));
391391
392392 /*
393− * 7. Change souce clock from SCLKMPLL(667Mhz)
393+ * 7. Change source clock from SCLKMPLL(667Mhz)
394394 * to SCLKA2M(200Mhz) in MFC_MUX and G3D MUX
395395 * (667/4=166)->(200/4=50)Mhz
396396 */
@@ -439,8 +439,8 @@ static int s5pv210_target(struct cpufreq_policy *policy, unsigned int index) · 42 unmodified lines
439439 }
440440
441441 /*
442− * L4 level need to change memory bus speed, hence onedram clock divier
443− * and memory refresh parameter should be changed
442+ * L4 level needs to change memory bus speed, hence ONEDRAM clock
443+ * divider and memory refresh parameter should be changed
444444 */
445445 if (bus_speed_changing) {
446446 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
2323
2424 void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity);
2525
26−DECLARE_PER_CPU(unsigned long, freq_scale);
26+DECLARE_PER_CPU(unsigned long, arch_freq_scale);
2727
2828 static inline unsigned long topology_get_freq_scale(int cpu)
2929 {
30− return per_cpu(freq_scale, cpu);
30+ return per_cpu(arch_freq_scale, cpu);
3131 }
3232
3333 void topology_set_freq_scale(const struct cpumask *cpus, unsigned long cur_freq,
3434 unsigned long max_freq);
3535 bool topology_scale_freq_invariant(void);
3636
37−bool arch_freq_counters_available(const struct cpumask *cpus);
37+enum scale_freq_source {
38+ SCALE_FREQ_SOURCE_CPUFREQ = 0,
39+ SCALE_FREQ_SOURCE_ARCH,
40+ SCALE_FREQ_SOURCE_CPPC,
41+};
42+
43+struct scale_freq_data {
44+ enum scale_freq_source source;
45+ void (*set_freq_scale)(void);
46+};
47+
48+void topology_scale_freq_tick(void);
49+void topology_set_scale_freq_source(struct scale_freq_data *data, const struct cpumask *cpus);
50+void topology_clear_scale_freq_source(enum scale_freq_source source, const struct cpumask *cpus);
3851
3952 DECLARE_PER_CPU(unsigned long, thermal_pressure);
4053
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
63846384 {
63856385 return __sched_setscheduler(p, attr, false, true);
63866386 }
6387+EXPORT_SYMBOL_GPL(sched_setattr_nocheck);
63876388
63886389 /**
63896390 * 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