Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'cpufreq-arm-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm

Merge CPUFreq updates for 6.18 from Viresh Kumar:

"- Minor improvements to Rust Cpumask APIs (Alice Ryhl, Baptiste Lepers,
and Shankari Anand).

- Minor cleanups and optimizations to various cpufreq drivers (Akhilesh
Patil, BowenYu, Dennis Beier, Liao Yuanhong, Zihuan Zhang, Florian
Fainelli, Taniya Das, Md Sadre Alam, and Christian Marangi).

- Enhancements for TI cpufreq driver (Judith Mendez, and Paresh Bhagat).

- Enhancements for mediatek cpufreq driver (Nicolas Frattaroli).

- Remove outdated cpufreq-dt.txt (Frank Li).

- Update MAINTAINERS for virtual-cpufreq maintainer (Saravana Kannan)."

* tag 'cpufreq-arm-updates-6.18' of git://git.kernel.org/pub/scm/linux/kernel/git/vireshk/pm: (28 commits)
cpufreq: mediatek: avoid redundant conditions
cpufreq/longhaul: handle NULL policy in longhaul_exit
cpufreq: tegra186: Use scope-based cleanup helper
cpufreq: mediatek: Use scope-based cleanup helper
cpufreq: s5pv210: Use scope-based cleanup helper
cpufreq: CPPC: Use scope-based cleanup helper
cpufreq: brcmstb-avs: Use scope-based cleanup helper
dt-bindings: Remove outdated cpufreq-dt.txt
arm64: dts: ti: k3-am62p: Fix supported hardware for 1GHz OPP
cpufreq: ti: Allow all silicon revisions to support OPPs
cpufreq: ti: Support more speed grades on AM62Px SoC
cpufreq: ti: Add support for AM62D2
cpufreq: dt-platdev: Blacklist ti,am62d2 SoC
rust: opp: update ARef and AlwaysRefCounted imports from sync::aref
cpufreq: mediatek-hw: don't use error path on NULL fdvfs
cpufreq: scmi: Account for malformed DT in scmi_dev_used_by_cpus()
rust: cpumask: Mark CpumaskVar as transparent
rust: cpumask: rename CpumaskVar::as[_mut]_ref to from_raw[_mut]
dt-bindings: cpufreq: cpufreq-qcom-hw: Add QCS615 compatible
MAINTAINERS: Add myself as virtual-cpufreq maintainer
...

+257 -125
-61
Documentation/devicetree/bindings/cpufreq/cpufreq-dt.txt
··· 1 - Generic cpufreq driver 2 - 3 - It is a generic DT based cpufreq driver for frequency management. It supports 4 - both uniprocessor (UP) and symmetric multiprocessor (SMP) systems which share 5 - clock and voltage across all CPUs. 6 - 7 - Both required and optional properties listed below must be defined 8 - under node /cpus/cpu@0. 9 - 10 - Required properties: 11 - - None 12 - 13 - Optional properties: 14 - - operating-points: Refer to Documentation/devicetree/bindings/opp/opp-v1.yaml for 15 - details. OPPs *must* be supplied either via DT, i.e. this property, or 16 - populated at runtime. 17 - - clock-latency: Specify the possible maximum transition latency for clock, 18 - in unit of nanoseconds. 19 - - voltage-tolerance: Specify the CPU voltage tolerance in percentage. 20 - - #cooling-cells: 21 - Please refer to 22 - Documentation/devicetree/bindings/thermal/thermal-cooling-devices.yaml. 23 - 24 - Examples: 25 - 26 - cpus { 27 - #address-cells = <1>; 28 - #size-cells = <0>; 29 - 30 - cpu@0 { 31 - compatible = "arm,cortex-a9"; 32 - reg = <0>; 33 - next-level-cache = <&L2>; 34 - operating-points = < 35 - /* kHz uV */ 36 - 792000 1100000 37 - 396000 950000 38 - 198000 850000 39 - >; 40 - clock-latency = <61036>; /* two CLK32 periods */ 41 - #cooling-cells = <2>; 42 - }; 43 - 44 - cpu@1 { 45 - compatible = "arm,cortex-a9"; 46 - reg = <1>; 47 - next-level-cache = <&L2>; 48 - }; 49 - 50 - cpu@2 { 51 - compatible = "arm,cortex-a9"; 52 - reg = <2>; 53 - next-level-cache = <&L2>; 54 - }; 55 - 56 - cpu@3 { 57 - compatible = "arm,cortex-a9"; 58 - reg = <3>; 59 - next-level-cache = <&L2>; 60 - }; 61 - };
+2
Documentation/devicetree/bindings/cpufreq/cpufreq-qcom-hw.yaml
··· 22 22 items: 23 23 - enum: 24 24 - qcom,qcm2290-cpufreq-hw 25 + - qcom,qcs615-cpufreq-hw 25 26 - qcom,sc7180-cpufreq-hw 26 27 - qcom,sc8180x-cpufreq-hw 27 28 - qcom,sdm670-cpufreq-hw ··· 133 132 compatible: 134 133 contains: 135 134 enum: 135 + - qcom,qcs615-cpufreq-hw 136 136 - qcom,qdu1000-cpufreq-epss 137 137 - qcom,sa8255p-cpufreq-epss 138 138 - qcom,sa8775p-cpufreq-epss
+82
Documentation/devicetree/bindings/cpufreq/mediatek,mt8196-cpufreq-hw.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/cpufreq/mediatek,mt8196-cpufreq-hw.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: MediaTek Hybrid CPUFreq for MT8196/MT6991 series SoCs 8 + 9 + maintainers: 10 + - Nicolas Frattaroli <nicolas.frattaroli@collabora.com> 11 + 12 + description: 13 + MT8196 uses CPUFreq management hardware that supports dynamic voltage 14 + frequency scaling (dvfs), and can support several performance domains. 15 + 16 + properties: 17 + compatible: 18 + const: mediatek,mt8196-cpufreq-hw 19 + 20 + reg: 21 + items: 22 + - description: FDVFS control register region 23 + - description: OPP tables and control for performance domain 0 24 + - description: OPP tables and control for performance domain 1 25 + - description: OPP tables and control for performance domain 2 26 + 27 + "#performance-domain-cells": 28 + const: 1 29 + 30 + required: 31 + - compatible 32 + - reg 33 + - "#performance-domain-cells" 34 + 35 + additionalProperties: false 36 + 37 + examples: 38 + - | 39 + cpus { 40 + #address-cells = <1>; 41 + #size-cells = <0>; 42 + 43 + cpu0: cpu@0 { 44 + device_type = "cpu"; 45 + compatible = "arm,cortex-a720"; 46 + enable-method = "psci"; 47 + performance-domains = <&performance 0>; 48 + reg = <0x000>; 49 + }; 50 + 51 + /* ... */ 52 + 53 + cpu6: cpu@600 { 54 + device_type = "cpu"; 55 + compatible = "arm,cortex-x4"; 56 + enable-method = "psci"; 57 + performance-domains = <&performance 1>; 58 + reg = <0x600>; 59 + }; 60 + 61 + cpu7: cpu@700 { 62 + device_type = "cpu"; 63 + compatible = "arm,cortex-x925"; 64 + enable-method = "psci"; 65 + performance-domains = <&performance 2>; 66 + reg = <0x700>; 67 + }; 68 + }; 69 + 70 + /* ... */ 71 + 72 + soc { 73 + #address-cells = <2>; 74 + #size-cells = <2>; 75 + 76 + performance: performance-controller@c2c2034 { 77 + compatible = "mediatek,mt8196-cpufreq-hw"; 78 + reg = <0 0xc220400 0 0x20>, <0 0xc2c0f20 0 0x120>, 79 + <0 0xc2c1040 0 0x120>, <0 0xc2c1160 0 0x120>; 80 + #performance-domain-cells = <1>; 81 + }; 82 + };
+6
MAINTAINERS
··· 6350 6350 F: rust/kernel/cpufreq.rs 6351 6351 F: tools/testing/selftests/cpufreq/ 6352 6352 6353 + CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ 6354 + M: Saravana Kannan <saravanak@google.com> 6355 + L: linux-pm@vger.kernel.org 6356 + S: Maintained 6357 + F: drivers/cpufreq/virtual-cpufreq.c 6358 + 6353 6359 CPU HOTPLUG 6354 6360 M: Thomas Gleixner <tglx@linutronix.de> 6355 6361 M: Peter Zijlstra <peterz@infradead.org>
+1 -1
arch/arm64/boot/dts/ti/k3-am62p5.dtsi
··· 135 135 136 136 opp-1000000000 { 137 137 opp-hz = /bits/ 64 <1000000000>; 138 - opp-supported-hw = <0x01 0x0006>; 138 + opp-supported-hw = <0x01 0x0007>; 139 139 clock-latency-ns = <6000000>; 140 140 }; 141 141
+1
drivers/cpufreq/airoha-cpufreq.c
··· 107 107 }; 108 108 109 109 static const struct of_device_id airoha_cpufreq_match_list[] __initconst = { 110 + { .compatible = "airoha,an7583" }, 110 111 { .compatible = "airoha,en7581" }, 111 112 {}, 112 113 };
+2 -2
drivers/cpufreq/armada-37xx-cpufreq.c
··· 265 265 */ 266 266 267 267 target_vm = avs_map[l0_vdd_min] - 100; 268 - target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 268 + target_vm = max(target_vm, MIN_VOLT_MV); 269 269 dvfs->avs[1] = armada_37xx_avs_val_match(target_vm); 270 270 271 271 /* ··· 273 273 * be larger than 1000mv 274 274 */ 275 275 target_vm = avs_map[l0_vdd_min] - 150; 276 - target_vm = target_vm > MIN_VOLT_MV ? target_vm : MIN_VOLT_MV; 276 + target_vm = max(target_vm, MIN_VOLT_MV); 277 277 dvfs->avs[2] = dvfs->avs[3] = armada_37xx_avs_val_match(target_vm); 278 278 279 279 /*
+1 -3
drivers/cpufreq/brcmstb-avs-cpufreq.c
··· 480 480 481 481 static unsigned int brcm_avs_cpufreq_get(unsigned int cpu) 482 482 { 483 - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 483 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 484 484 struct private_data *priv; 485 485 486 486 if (!policy) 487 487 return 0; 488 488 489 489 priv = policy->driver_data; 490 - 491 - cpufreq_cpu_put(policy); 492 490 493 491 return brcm_avs_get_frequency(priv->base); 494 492 }
+5 -11
drivers/cpufreq/cppc_cpufreq.c
··· 50 50 static DEFINE_PER_CPU(struct cppc_freq_invariance, cppc_freq_inv); 51 51 static struct kthread_worker *kworker_fie; 52 52 53 - static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, 54 - struct cppc_perf_fb_ctrs *fb_ctrs_t0, 53 + static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0, 55 54 struct cppc_perf_fb_ctrs *fb_ctrs_t1); 56 55 57 56 /** ··· 86 87 return; 87 88 } 88 89 89 - perf = cppc_perf_from_fbctrs(cpu_data, &cppc_fi->prev_perf_fb_ctrs, 90 - &fb_ctrs); 90 + perf = cppc_perf_from_fbctrs(&cppc_fi->prev_perf_fb_ctrs, &fb_ctrs); 91 91 if (!perf) 92 92 return; 93 93 ··· 682 684 return (u32)t1 - (u32)t0; 683 685 } 684 686 685 - static int cppc_perf_from_fbctrs(struct cppc_cpudata *cpu_data, 686 - struct cppc_perf_fb_ctrs *fb_ctrs_t0, 687 + static int cppc_perf_from_fbctrs(struct cppc_perf_fb_ctrs *fb_ctrs_t0, 687 688 struct cppc_perf_fb_ctrs *fb_ctrs_t1) 688 689 { 689 690 u64 delta_reference, delta_delivered; ··· 722 725 723 726 static unsigned int cppc_cpufreq_get_rate(unsigned int cpu) 724 727 { 728 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 725 729 struct cppc_perf_fb_ctrs fb_ctrs_t0 = {0}, fb_ctrs_t1 = {0}; 726 - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); 727 730 struct cppc_cpudata *cpu_data; 728 731 u64 delivered_perf; 729 732 int ret; ··· 732 735 return 0; 733 736 734 737 cpu_data = policy->driver_data; 735 - 736 - cpufreq_cpu_put(policy); 737 738 738 739 ret = cppc_get_perf_ctrs_sample(cpu, &fb_ctrs_t0, &fb_ctrs_t1); 739 740 if (ret) { ··· 742 747 return 0; 743 748 } 744 749 745 - delivered_perf = cppc_perf_from_fbctrs(cpu_data, &fb_ctrs_t0, 746 - &fb_ctrs_t1); 750 + delivered_perf = cppc_perf_from_fbctrs(&fb_ctrs_t0, &fb_ctrs_t1); 747 751 if (!delivered_perf) 748 752 goto out_invalid_counters; 749 753
+3
drivers/cpufreq/cpufreq-dt-platdev.c
··· 103 103 * platforms using "operating-points-v2" property. 104 104 */ 105 105 static const struct of_device_id blocklist[] __initconst = { 106 + { .compatible = "airoha,an7583", }, 106 107 { .compatible = "airoha,en7581", }, 107 108 108 109 { .compatible = "allwinner,sun50i-a100" }, ··· 189 188 { .compatible = "ti,omap3", }, 190 189 { .compatible = "ti,am625", }, 191 190 { .compatible = "ti,am62a7", }, 191 + { .compatible = "ti,am62d2", }, 192 192 { .compatible = "ti,am62p5", }, 193 193 194 194 { .compatible = "qcom,ipq5332", }, 195 + { .compatible = "qcom,ipq5424", }, 195 196 { .compatible = "qcom,ipq6018", }, 196 197 { .compatible = "qcom,ipq8064", }, 197 198 { .compatible = "qcom,ipq8074", },
+3
drivers/cpufreq/longhaul.c
··· 953 953 struct cpufreq_policy *policy = cpufreq_cpu_get(0); 954 954 int i; 955 955 956 + if (unlikely(!policy)) 957 + return; 958 + 956 959 for (i = 0; i < numscales; i++) { 957 960 if (mults[i] == maxmult) { 958 961 struct cpufreq_freqs freqs;
+109 -23
drivers/cpufreq/mediatek-cpufreq-hw.c
··· 24 24 #define POLL_USEC 1000 25 25 #define TIMEOUT_USEC 300000 26 26 27 + #define FDVFS_FDIV_HZ (26 * 1000) 28 + 27 29 enum { 28 30 REG_FREQ_LUT_TABLE, 29 31 REG_FREQ_ENABLE, ··· 37 35 REG_ARRAY_SIZE, 38 36 }; 39 37 40 - struct mtk_cpufreq_data { 38 + struct mtk_cpufreq_priv { 39 + struct device *dev; 40 + const struct mtk_cpufreq_variant *variant; 41 + void __iomem *fdvfs; 42 + }; 43 + 44 + struct mtk_cpufreq_domain { 45 + struct mtk_cpufreq_priv *parent; 41 46 struct cpufreq_frequency_table *table; 42 47 void __iomem *reg_bases[REG_ARRAY_SIZE]; 43 48 struct resource *res; ··· 52 43 int nr_opp; 53 44 }; 54 45 55 - static const u16 cpufreq_mtk_offsets[REG_ARRAY_SIZE] = { 56 - [REG_FREQ_LUT_TABLE] = 0x0, 57 - [REG_FREQ_ENABLE] = 0x84, 58 - [REG_FREQ_PERF_STATE] = 0x88, 59 - [REG_FREQ_HW_STATE] = 0x8c, 60 - [REG_EM_POWER_TBL] = 0x90, 61 - [REG_FREQ_LATENCY] = 0x110, 46 + struct mtk_cpufreq_variant { 47 + int (*init)(struct mtk_cpufreq_priv *priv); 48 + const u16 reg_offsets[REG_ARRAY_SIZE]; 49 + const bool is_hybrid_dvfs; 50 + }; 51 + 52 + static const struct mtk_cpufreq_variant cpufreq_mtk_base_variant = { 53 + .reg_offsets = { 54 + [REG_FREQ_LUT_TABLE] = 0x0, 55 + [REG_FREQ_ENABLE] = 0x84, 56 + [REG_FREQ_PERF_STATE] = 0x88, 57 + [REG_FREQ_HW_STATE] = 0x8c, 58 + [REG_EM_POWER_TBL] = 0x90, 59 + [REG_FREQ_LATENCY] = 0x110, 60 + }, 61 + }; 62 + 63 + static int mtk_cpufreq_hw_mt8196_init(struct mtk_cpufreq_priv *priv) 64 + { 65 + priv->fdvfs = devm_of_iomap(priv->dev, priv->dev->of_node, 0, NULL); 66 + if (IS_ERR(priv->fdvfs)) 67 + return dev_err_probe(priv->dev, PTR_ERR(priv->fdvfs), 68 + "failed to get fdvfs iomem\n"); 69 + 70 + return 0; 71 + } 72 + 73 + static const struct mtk_cpufreq_variant cpufreq_mtk_mt8196_variant = { 74 + .init = mtk_cpufreq_hw_mt8196_init, 75 + .reg_offsets = { 76 + [REG_FREQ_LUT_TABLE] = 0x0, 77 + [REG_FREQ_ENABLE] = 0x84, 78 + [REG_FREQ_PERF_STATE] = 0x88, 79 + [REG_FREQ_HW_STATE] = 0x8c, 80 + [REG_EM_POWER_TBL] = 0x90, 81 + [REG_FREQ_LATENCY] = 0x114, 82 + }, 83 + .is_hybrid_dvfs = true, 62 84 }; 63 85 64 86 static int __maybe_unused 65 87 mtk_cpufreq_get_cpu_power(struct device *cpu_dev, unsigned long *uW, 66 88 unsigned long *KHz) 67 89 { 68 - struct mtk_cpufreq_data *data; 90 + struct mtk_cpufreq_domain *data; 69 91 struct cpufreq_policy *policy; 70 92 int i; 71 93 ··· 120 80 return 0; 121 81 } 122 82 83 + static void mtk_cpufreq_hw_fdvfs_switch(unsigned int target_freq, 84 + struct cpufreq_policy *policy) 85 + { 86 + struct mtk_cpufreq_domain *data = policy->driver_data; 87 + struct mtk_cpufreq_priv *priv = data->parent; 88 + unsigned int cpu; 89 + 90 + target_freq = DIV_ROUND_UP(target_freq, FDVFS_FDIV_HZ); 91 + for_each_cpu(cpu, policy->real_cpus) { 92 + writel_relaxed(target_freq, priv->fdvfs + cpu * 4); 93 + } 94 + } 95 + 123 96 static int mtk_cpufreq_hw_target_index(struct cpufreq_policy *policy, 124 97 unsigned int index) 125 98 { 126 - struct mtk_cpufreq_data *data = policy->driver_data; 99 + struct mtk_cpufreq_domain *data = policy->driver_data; 100 + unsigned int target_freq; 127 101 128 - writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 102 + if (data->parent->fdvfs) { 103 + target_freq = policy->freq_table[index].frequency; 104 + mtk_cpufreq_hw_fdvfs_switch(target_freq, policy); 105 + } else { 106 + writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 107 + } 129 108 130 109 return 0; 131 110 } 132 111 133 112 static unsigned int mtk_cpufreq_hw_get(unsigned int cpu) 134 113 { 135 - struct mtk_cpufreq_data *data; 114 + struct mtk_cpufreq_domain *data; 136 115 struct cpufreq_policy *policy; 137 116 unsigned int index; 138 117 ··· 170 111 static unsigned int mtk_cpufreq_hw_fast_switch(struct cpufreq_policy *policy, 171 112 unsigned int target_freq) 172 113 { 173 - struct mtk_cpufreq_data *data = policy->driver_data; 114 + struct mtk_cpufreq_domain *data = policy->driver_data; 174 115 unsigned int index; 175 116 176 117 index = cpufreq_table_find_index_dl(policy, target_freq, false); 177 118 178 - writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 119 + if (data->parent->fdvfs) 120 + mtk_cpufreq_hw_fdvfs_switch(target_freq, policy); 121 + else 122 + writel_relaxed(index, data->reg_bases[REG_FREQ_PERF_STATE]); 179 123 180 124 return policy->freq_table[index].frequency; 181 125 } 182 126 183 127 static int mtk_cpu_create_freq_table(struct platform_device *pdev, 184 - struct mtk_cpufreq_data *data) 128 + struct mtk_cpufreq_domain *data) 185 129 { 186 130 struct device *dev = &pdev->dev; 187 131 u32 temp, i, freq, prev_freq = 0; ··· 219 157 220 158 static int mtk_cpu_resources_init(struct platform_device *pdev, 221 159 struct cpufreq_policy *policy, 222 - const u16 *offsets) 160 + struct mtk_cpufreq_priv *priv) 223 161 { 224 - struct mtk_cpufreq_data *data; 162 + struct mtk_cpufreq_domain *data; 225 163 struct device *dev = &pdev->dev; 226 164 struct resource *res; 227 165 struct of_phandle_args args; ··· 241 179 242 180 index = args.args[0]; 243 181 of_node_put(args.np); 182 + 183 + /* 184 + * In a cpufreq with hybrid DVFS, such as the MT8196, the first declared 185 + * register range is for FDVFS, followed by the frequency domain MMIOs. 186 + */ 187 + if (priv->variant->is_hybrid_dvfs) 188 + index++; 189 + 190 + data->parent = priv; 244 191 245 192 res = platform_get_resource(pdev, IORESOURCE_MEM, index); 246 193 if (!res) { ··· 273 202 data->res = res; 274 203 275 204 for (i = REG_FREQ_LUT_TABLE; i < REG_ARRAY_SIZE; i++) 276 - data->reg_bases[i] = base + offsets[i]; 205 + data->reg_bases[i] = base + priv->variant->reg_offsets[i]; 277 206 278 207 ret = mtk_cpu_create_freq_table(pdev, data); 279 208 if (ret) { ··· 294 223 { 295 224 struct platform_device *pdev = cpufreq_get_driver_data(); 296 225 int sig, pwr_hw = CPUFREQ_HW_STATUS | SVS_HW_STATUS; 297 - struct mtk_cpufreq_data *data; 226 + struct mtk_cpufreq_domain *data; 298 227 unsigned int latency; 299 228 int ret; 300 229 ··· 333 262 334 263 static void mtk_cpufreq_hw_cpu_exit(struct cpufreq_policy *policy) 335 264 { 336 - struct mtk_cpufreq_data *data = policy->driver_data; 265 + struct mtk_cpufreq_domain *data = policy->driver_data; 337 266 struct resource *res = data->res; 338 267 void __iomem *base = data->base; 339 268 ··· 346 275 static void mtk_cpufreq_register_em(struct cpufreq_policy *policy) 347 276 { 348 277 struct em_data_callback em_cb = EM_DATA_CB(mtk_cpufreq_get_cpu_power); 349 - struct mtk_cpufreq_data *data = policy->driver_data; 278 + struct mtk_cpufreq_domain *data = policy->driver_data; 350 279 351 280 em_dev_register_perf_domain(get_cpu_device(policy->cpu), data->nr_opp, 352 281 &em_cb, policy->cpus, true); ··· 368 297 369 298 static int mtk_cpufreq_hw_driver_probe(struct platform_device *pdev) 370 299 { 300 + struct mtk_cpufreq_priv *priv; 371 301 const void *data; 372 302 int ret, cpu; 373 303 struct device *cpu_dev; ··· 392 320 if (!data) 393 321 return -EINVAL; 394 322 395 - platform_set_drvdata(pdev, (void *) data); 323 + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 324 + if (!priv) 325 + return -ENOMEM; 326 + 327 + priv->variant = data; 328 + priv->dev = &pdev->dev; 329 + 330 + if (priv->variant->init) { 331 + ret = priv->variant->init(priv); 332 + if (ret) 333 + return ret; 334 + } 335 + 336 + platform_set_drvdata(pdev, priv); 396 337 cpufreq_mtk_hw_driver.driver_data = pdev; 397 338 398 339 ret = cpufreq_register_driver(&cpufreq_mtk_hw_driver); ··· 421 336 } 422 337 423 338 static const struct of_device_id mtk_cpufreq_hw_match[] = { 424 - { .compatible = "mediatek,cpufreq-hw", .data = &cpufreq_mtk_offsets }, 339 + { .compatible = "mediatek,cpufreq-hw", .data = &cpufreq_mtk_base_variant }, 340 + { .compatible = "mediatek,mt8196-cpufreq-hw", .data = &cpufreq_mtk_mt8196_variant }, 425 341 {} 426 342 }; 427 343 MODULE_DEVICE_TABLE(of, mtk_cpufreq_hw_match);
+5 -6
drivers/cpufreq/mediatek-cpufreq.c
··· 123 123 soc_data->sram_max_volt); 124 124 return ret; 125 125 } 126 - } else if (pre_vproc > new_vproc) { 126 + } else { 127 127 vproc = max(new_vproc, 128 128 pre_vsram - soc_data->max_volt_shift); 129 129 ret = regulator_set_voltage(proc_reg, vproc, ··· 320 320 struct dev_pm_opp *new_opp; 321 321 struct mtk_cpu_dvfs_info *info; 322 322 unsigned long freq, volt; 323 - struct cpufreq_policy *policy; 324 323 int ret = 0; 325 324 326 325 info = container_of(nb, struct mtk_cpu_dvfs_info, opp_nb); ··· 352 353 } 353 354 354 355 dev_pm_opp_put(new_opp); 355 - policy = cpufreq_cpu_get(info->opp_cpu); 356 - if (policy) { 356 + 357 + struct cpufreq_policy *policy __free(put_cpufreq_policy) 358 + = cpufreq_cpu_get(info->opp_cpu); 359 + if (policy) 357 360 cpufreq_driver_target(policy, freq / 1000, 358 361 CPUFREQ_RELATION_L); 359 - cpufreq_cpu_put(policy); 360 - } 361 362 } 362 363 } 363 364
+5
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 200 200 case QCOM_ID_IPQ9574: 201 201 drv->versions = 1 << (unsigned int)(*speedbin); 202 202 break; 203 + case QCOM_ID_IPQ5424: 204 + case QCOM_ID_IPQ5404: 205 + drv->versions = (*speedbin == 0x3b) ? BIT(1) : BIT(0); 206 + break; 203 207 case QCOM_ID_MSM8996SG: 204 208 case QCOM_ID_APQ8096SG: 205 209 drv->versions = 1 << ((unsigned int)(*speedbin) + 4); ··· 595 591 { .compatible = "qcom,msm8996", .data = &match_data_kryo }, 596 592 { .compatible = "qcom,qcs404", .data = &match_data_qcs404 }, 597 593 { .compatible = "qcom,ipq5332", .data = &match_data_kryo }, 594 + { .compatible = "qcom,ipq5424", .data = &match_data_kryo }, 598 595 { .compatible = "qcom,ipq6018", .data = &match_data_ipq6018 }, 599 596 { .compatible = "qcom,ipq8064", .data = &match_data_ipq8064 }, 600 597 { .compatible = "qcom,ipq8074", .data = &match_data_ipq8074 },
+1 -3
drivers/cpufreq/s5pv210-cpufreq.c
··· 554 554 static int s5pv210_cpufreq_reboot_notifier_event(struct notifier_block *this, 555 555 unsigned long event, void *ptr) 556 556 { 557 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(0); 557 558 int ret; 558 - struct cpufreq_policy *policy; 559 559 560 - policy = cpufreq_cpu_get(0); 561 560 if (!policy) { 562 561 pr_debug("cpufreq: get no policy for cpu0\n"); 563 562 return NOTIFY_BAD; 564 563 } 565 564 566 565 ret = cpufreq_driver_target(policy, SLEEP_FREQ, 0); 567 - cpufreq_cpu_put(policy); 568 566 569 567 if (ret < 0) 570 568 return NOTIFY_BAD;
+10
drivers/cpufreq/scmi-cpufreq.c
··· 15 15 #include <linux/energy_model.h> 16 16 #include <linux/export.h> 17 17 #include <linux/module.h> 18 + #include <linux/of.h> 18 19 #include <linux/pm_opp.h> 19 20 #include <linux/pm_qos.h> 20 21 #include <linux/slab.h> ··· 424 423 if (np == scmi_np) 425 424 return true; 426 425 } 426 + 427 + /* 428 + * Older Broadcom STB chips had a "clocks" property for CPU node(s) 429 + * that did not match the SCMI performance protocol node, if we got 430 + * there, it means we had such an older Device Tree, therefore return 431 + * true to preserve backwards compatibility. 432 + */ 433 + if (of_machine_is_compatible("brcm,brcmstb")) 434 + return true; 427 435 428 436 return false; 429 437 }
+1 -3
drivers/cpufreq/tegra186-cpufreq.c
··· 103 103 104 104 static unsigned int tegra186_cpufreq_get(unsigned int cpu) 105 105 { 106 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 106 107 struct tegra186_cpufreq_data *data = cpufreq_get_driver_data(); 107 108 struct tegra186_cpufreq_cluster *cluster; 108 - struct cpufreq_policy *policy; 109 109 unsigned int edvd_offset, cluster_id; 110 110 u32 ndiv; 111 111 112 - policy = cpufreq_cpu_get(cpu); 113 112 if (!policy) 114 113 return 0; 115 114 ··· 116 117 ndiv = readl(data->regs + edvd_offset) & EDVD_CORE_VOLT_FREQ_F_MASK; 117 118 cluster_id = data->cpus[policy->cpu].bpmp_cluster_id; 118 119 cluster = &data->clusters[cluster_id]; 119 - cpufreq_cpu_put(policy); 120 120 121 121 return (cluster->ref_clk_khz * ndiv) / cluster->div; 122 122 }
+9 -3
drivers/cpufreq/ti-cpufreq.c
··· 72 72 73 73 #define AM62P5_EFUSE_O_MPU_OPP 15 74 74 #define AM62P5_EFUSE_S_MPU_OPP 19 75 + #define AM62P5_EFUSE_T_MPU_OPP 20 75 76 #define AM62P5_EFUSE_U_MPU_OPP 21 77 + #define AM62P5_EFUSE_V_MPU_OPP 22 76 78 77 79 #define AM62P5_SUPPORT_O_MPU_OPP BIT(0) 78 80 #define AM62P5_SUPPORT_U_MPU_OPP BIT(2) ··· 155 153 unsigned long calculated_efuse = AM62P5_SUPPORT_O_MPU_OPP; 156 154 157 155 switch (efuse) { 156 + case AM62P5_EFUSE_V_MPU_OPP: 158 157 case AM62P5_EFUSE_U_MPU_OPP: 158 + case AM62P5_EFUSE_T_MPU_OPP: 159 159 case AM62P5_EFUSE_S_MPU_OPP: 160 160 calculated_efuse |= AM62P5_SUPPORT_U_MPU_OPP; 161 161 fallthrough; ··· 311 307 }; 312 308 313 309 static const struct soc_device_attribute k3_cpufreq_soc[] = { 314 - { .family = "AM62X", .revision = "SR1.0" }, 315 - { .family = "AM62AX", .revision = "SR1.0" }, 316 - { .family = "AM62PX", .revision = "SR1.0" }, 310 + { .family = "AM62X", }, 311 + { .family = "AM62AX", }, 312 + { .family = "AM62PX", }, 313 + { .family = "AM62DX", }, 317 314 { /* sentinel */ } 318 315 }; 319 316 ··· 462 457 { .compatible = "ti,omap36xx", .data = &omap36xx_soc_data, }, 463 458 { .compatible = "ti,am625", .data = &am625_soc_data, }, 464 459 { .compatible = "ti,am62a7", .data = &am62a7_soc_data, }, 460 + { .compatible = "ti,am62d2", .data = &am62a7_soc_data, }, 465 461 { .compatible = "ti,am62p5", .data = &am62p5_soc_data, }, 466 462 /* legacy */ 467 463 { .compatible = "ti,omap3430", .data = &omap34xx_soc_data, },
+1 -1
rust/kernel/cpufreq.rs
··· 543 543 pub fn cpus(&mut self) -> &mut cpumask::Cpumask { 544 544 // SAFETY: The pointer to `cpus` is valid for writing and remains valid for the lifetime of 545 545 // the returned reference. 546 - unsafe { cpumask::CpumaskVar::as_mut_ref(&mut self.as_mut_ref().cpus) } 546 + unsafe { cpumask::CpumaskVar::from_raw_mut(&mut self.as_mut_ref().cpus) } 547 547 } 548 548 549 549 /// Sets clock for the [`Policy`].
+3 -2
rust/kernel/cpumask.rs
··· 212 212 /// } 213 213 /// assert_eq!(mask2.weight(), count); 214 214 /// ``` 215 + #[repr(transparent)] 215 216 pub struct CpumaskVar { 216 217 #[cfg(CONFIG_CPUMASK_OFFSTACK)] 217 218 ptr: NonNull<Cpumask>, ··· 271 270 /// 272 271 /// The caller must ensure that `ptr` is valid for writing and remains valid for the lifetime 273 272 /// of the returned reference. 274 - pub unsafe fn as_mut_ref<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self { 273 + pub unsafe fn from_raw_mut<'a>(ptr: *mut bindings::cpumask_var_t) -> &'a mut Self { 275 274 // SAFETY: Guaranteed by the safety requirements of the function. 276 275 // 277 276 // INVARIANT: The caller ensures that `ptr` is valid for writing and remains valid for the ··· 285 284 /// 286 285 /// The caller must ensure that `ptr` is valid for reading and remains valid for the lifetime 287 286 /// of the returned reference. 288 - pub unsafe fn as_ref<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self { 287 + pub unsafe fn from_raw<'a>(ptr: *const bindings::cpumask_var_t) -> &'a Self { 289 288 // SAFETY: Guaranteed by the safety requirements of the function. 290 289 // 291 290 // INVARIANT: The caller ensures that `ptr` is valid for reading and remains valid for the
+7 -6
rust/kernel/opp.rs
··· 16 16 ffi::c_ulong, 17 17 prelude::*, 18 18 str::CString, 19 - types::{ARef, AlwaysRefCounted, Opaque}, 19 + sync::aref::{ARef, AlwaysRefCounted}, 20 + types::Opaque, 20 21 }; 21 22 22 23 #[cfg(CONFIG_CPU_FREQ)] ··· 163 162 /// use kernel::device::Device; 164 163 /// use kernel::error::Result; 165 164 /// use kernel::opp::{Data, MicroVolt, Token}; 166 - /// use kernel::types::ARef; 165 + /// use kernel::sync::aref::ARef; 167 166 /// 168 167 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 169 168 /// let data = Data::new(freq, volt, level, false); ··· 212 211 /// use kernel::device::Device; 213 212 /// use kernel::error::Result; 214 213 /// use kernel::opp::{Data, MicroVolt, Token}; 215 - /// use kernel::types::ARef; 214 + /// use kernel::sync::aref::ARef; 216 215 /// 217 216 /// fn create_opp(dev: &ARef<Device>, freq: Hertz, volt: MicroVolt, level: u32) -> Result<Token> { 218 217 /// let data = Data::new(freq, volt, level, false); ··· 263 262 /// use kernel::clk::Hertz; 264 263 /// use kernel::error::Result; 265 264 /// use kernel::opp::{OPP, SearchType, Table}; 266 - /// use kernel::types::ARef; 265 + /// use kernel::sync::aref::ARef; 267 266 /// 268 267 /// fn find_opp(table: &Table, freq: Hertz) -> Result<ARef<OPP>> { 269 268 /// let opp = table.opp_from_freq(freq, Some(true), None, SearchType::Exact)?; ··· 336 335 /// use kernel::error::Result; 337 336 /// use kernel::opp::{Config, ConfigOps, ConfigToken}; 338 337 /// use kernel::str::CString; 339 - /// use kernel::types::ARef; 338 + /// use kernel::sync::aref::ARef; 340 339 /// use kernel::macros::vtable; 341 340 /// 342 341 /// #[derive(Default)] ··· 582 581 /// use kernel::device::Device; 583 582 /// use kernel::error::Result; 584 583 /// use kernel::opp::Table; 585 - /// use kernel::types::ARef; 584 + /// use kernel::sync::aref::ARef; 586 585 /// 587 586 /// fn get_table(dev: &ARef<Device>, mask: &mut Cpumask, freq: Hertz) -> Result<Table> { 588 587 /// let mut opp_table = Table::from_of_cpumask(dev, mask)?;