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

Configure Feed

Select the types of activity you want to include in your feed.

Merge back earlier cpufreq material for 6.18

+430 -328
-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
··· 6349 6349 F: rust/kernel/cpufreq.rs 6350 6350 F: tools/testing/selftests/cpufreq/ 6351 6351 6352 + CPU FREQUENCY DRIVERS - VIRTUAL MACHINE CPUFREQ 6353 + M: Saravana Kannan <saravanak@google.com> 6354 + L: linux-pm@vger.kernel.org 6355 + S: Maintained 6356 + F: drivers/cpufreq/virtual-cpufreq.c 6357 + 6352 6358 CPU HOTPLUG 6353 6359 M: Thomas Gleixner <tglx@linutronix.de> 6354 6360 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 -8
drivers/cpufreq/acpi-cpufreq.c
··· 318 318 return cmd.val; 319 319 } 320 320 321 - /* Called via smp_call_function_many(), on the target CPUs */ 322 321 static void do_drv_write(void *_cmd) 323 322 { 324 323 struct drv_cmd *cmd = _cmd; ··· 334 335 .val = val, 335 336 .func.write = data->cpu_freq_write, 336 337 }; 337 - int this_cpu; 338 338 339 - this_cpu = get_cpu(); 340 - if (cpumask_test_cpu(this_cpu, mask)) 341 - do_drv_write(&cmd); 342 - 343 - smp_call_function_many(mask, do_drv_write, &cmd, 1); 344 - put_cpu(); 339 + on_each_cpu_mask(mask, do_drv_write, &cmd, true); 345 340 } 346 341 347 342 static u32 get_cur_val(const struct cpumask *mask, struct acpi_cpufreq_data *data)
+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", },
+15 -29
drivers/cpufreq/cpufreq.c
··· 664 664 665 665 static unsigned int cpufreq_parse_policy(char *str_governor) 666 666 { 667 - if (!strncasecmp(str_governor, "performance", CPUFREQ_NAME_LEN)) 667 + if (!strncasecmp(str_governor, "performance", strlen("performance"))) 668 668 return CPUFREQ_POLICY_PERFORMANCE; 669 669 670 - if (!strncasecmp(str_governor, "powersave", CPUFREQ_NAME_LEN)) 670 + if (!strncasecmp(str_governor, "powersave", strlen("powersave"))) 671 671 return CPUFREQ_POLICY_POWERSAVE; 672 672 673 673 return CPUFREQ_POLICY_UNKNOWN; ··· 914 914 const char *buf, size_t count) 915 915 { 916 916 unsigned int freq = 0; 917 - unsigned int ret; 917 + int ret; 918 918 919 919 if (!policy->governor || !policy->governor->store_setspeed) 920 920 return -EINVAL; ··· 1121 1121 1122 1122 if (has_target()) { 1123 1123 /* Update policy governor to the one used before hotplug. */ 1124 - gov = get_governor(policy->last_governor); 1124 + if (policy->last_governor[0] != '\0') 1125 + gov = get_governor(policy->last_governor); 1125 1126 if (gov) { 1126 1127 pr_debug("Restoring governor %s for cpu %d\n", 1127 1128 gov->name, policy->cpu); ··· 1845 1844 */ 1846 1845 unsigned int cpufreq_quick_get(unsigned int cpu) 1847 1846 { 1848 - struct cpufreq_policy *policy __free(put_cpufreq_policy) = NULL; 1849 1847 unsigned long flags; 1850 1848 1851 1849 read_lock_irqsave(&cpufreq_driver_lock, flags); ··· 1859 1859 1860 1860 read_unlock_irqrestore(&cpufreq_driver_lock, flags); 1861 1861 1862 - policy = cpufreq_cpu_get(cpu); 1862 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1863 1863 if (policy) 1864 1864 return policy->cur; 1865 1865 ··· 1875 1875 */ 1876 1876 unsigned int cpufreq_quick_get_max(unsigned int cpu) 1877 1877 { 1878 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1879 - 1880 - policy = cpufreq_cpu_get(cpu); 1878 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1881 1879 if (policy) 1882 1880 return policy->max; 1883 1881 ··· 1891 1893 */ 1892 1894 __weak unsigned int cpufreq_get_hw_max_freq(unsigned int cpu) 1893 1895 { 1894 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1895 - 1896 - policy = cpufreq_cpu_get(cpu); 1896 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1897 1897 if (policy) 1898 1898 return policy->cpuinfo.max_freq; 1899 1899 ··· 1915 1919 */ 1916 1920 unsigned int cpufreq_get(unsigned int cpu) 1917 1921 { 1918 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1919 - 1920 - policy = cpufreq_cpu_get(cpu); 1922 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1921 1923 if (!policy) 1922 1924 return 0; 1923 1925 ··· 2744 2750 */ 2745 2751 void cpufreq_update_policy(unsigned int cpu) 2746 2752 { 2747 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 2748 - 2749 - policy = cpufreq_cpu_get(cpu); 2753 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 2750 2754 if (!policy) 2751 2755 return; 2752 2756 ··· 2761 2769 */ 2762 2770 void cpufreq_update_limits(unsigned int cpu) 2763 2771 { 2764 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 2765 - 2766 - policy = cpufreq_cpu_get(cpu); 2772 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 2767 2773 if (!policy) 2768 2774 return; 2769 2775 ··· 2782 2792 if (!policy->freq_table) 2783 2793 return -ENXIO; 2784 2794 2785 - ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 2795 + ret = cpufreq_frequency_table_cpuinfo(policy); 2786 2796 if (ret) { 2787 2797 pr_err("%s: Policy frequency update failed\n", __func__); 2788 2798 return ret; ··· 2911 2921 return -EPROBE_DEFER; 2912 2922 2913 2923 if (!driver_data || !driver_data->verify || !driver_data->init || 2914 - !(driver_data->setpolicy || driver_data->target_index || 2915 - driver_data->target) || 2916 - (driver_data->setpolicy && (driver_data->target_index || 2917 - driver_data->target)) || 2924 + (driver_data->target_index && driver_data->target) || 2925 + (!!driver_data->setpolicy == (driver_data->target_index || driver_data->target)) || 2918 2926 (!driver_data->get_intermediate != !driver_data->target_intermediate) || 2919 2927 (!driver_data->online != !driver_data->offline) || 2920 2928 (driver_data->adjust_perf && !driver_data->fast_switch)) ··· 3046 3058 3047 3059 static bool cpufreq_policy_is_good_for_eas(unsigned int cpu) 3048 3060 { 3049 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 3050 - 3051 - policy = cpufreq_cpu_get(cpu); 3061 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 3052 3062 if (!policy) { 3053 3063 pr_debug("cpufreq policy not set for CPU: %d\n", cpu); 3054 3064 return false;
+12 -12
drivers/cpufreq/cpufreq_conservative.c
··· 152 152 struct dbs_data *dbs_data = to_dbs_data(attr_set); 153 153 unsigned int input; 154 154 int ret; 155 - ret = sscanf(buf, "%u", &input); 155 + ret = kstrtouint(buf, 0, &input); 156 156 157 - if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 157 + if (ret || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) 158 158 return -EINVAL; 159 159 160 160 dbs_data->sampling_down_factor = input; ··· 168 168 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 169 169 unsigned int input; 170 170 int ret; 171 - ret = sscanf(buf, "%u", &input); 171 + ret = kstrtouint(buf, 0, &input); 172 172 173 - if (ret != 1 || input > 100 || input <= cs_tuners->down_threshold) 173 + if (ret || input > 100 || input <= cs_tuners->down_threshold) 174 174 return -EINVAL; 175 175 176 176 dbs_data->up_threshold = input; ··· 184 184 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 185 185 unsigned int input; 186 186 int ret; 187 - ret = sscanf(buf, "%u", &input); 187 + ret = kstrtouint(buf, 0, &input); 188 188 189 189 /* cannot be lower than 1 otherwise freq will not fall */ 190 - if (ret != 1 || input < 1 || input >= dbs_data->up_threshold) 190 + if (ret || input < 1 || input >= dbs_data->up_threshold) 191 191 return -EINVAL; 192 192 193 193 cs_tuners->down_threshold = input; ··· 201 201 unsigned int input; 202 202 int ret; 203 203 204 - ret = sscanf(buf, "%u", &input); 205 - if (ret != 1) 206 - return -EINVAL; 204 + ret = kstrtouint(buf, 0, &input); 205 + if (ret) 206 + return ret; 207 207 208 208 if (input > 1) 209 209 input = 1; ··· 226 226 struct cs_dbs_tuners *cs_tuners = dbs_data->tuners; 227 227 unsigned int input; 228 228 int ret; 229 - ret = sscanf(buf, "%u", &input); 229 + ret = kstrtouint(buf, 0, &input); 230 230 231 - if (ret != 1) 232 - return -EINVAL; 231 + if (ret) 232 + return ret; 233 233 234 234 if (input > 100) 235 235 input = 100;
+1 -24
drivers/cpufreq/cpufreq_ondemand.c
··· 30 30 static unsigned int default_powersave_bias; 31 31 32 32 /* 33 - * Not all CPUs want IO time to be accounted as busy; this depends on how 34 - * efficient idling at a higher frequency/voltage is. 35 - * Pavel Machek says this is not so for various generations of AMD and old 36 - * Intel systems. 37 - * Mike Chan (android.com) claims this is also not true for ARM. 38 - * Because of this, whitelist specific known (series) of CPUs by default, and 39 - * leave all others up to the user. 40 - */ 41 - static int should_io_be_busy(void) 42 - { 43 - #if defined(CONFIG_X86) 44 - /* 45 - * For Intel, Core 2 (model 15) and later have an efficient idle. 46 - */ 47 - if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 48 - boot_cpu_data.x86 == 6 && 49 - boot_cpu_data.x86_model >= 15) 50 - return 1; 51 - #endif 52 - return 0; 53 - } 54 - 55 - /* 56 33 * Find right freq to be set now with powersave_bias on. 57 34 * Returns the freq_hi to be used right now and will set freq_hi_delay_us, 58 35 * freq_lo, and freq_lo_delay_us in percpu area for averaging freqs. ··· 354 377 dbs_data->sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR; 355 378 dbs_data->ignore_nice_load = 0; 356 379 tuners->powersave_bias = default_powersave_bias; 357 - dbs_data->io_is_busy = should_io_be_busy(); 380 + dbs_data->io_is_busy = od_should_io_be_busy(); 358 381 359 382 dbs_data->tuners = tuners; 360 383 return 0;
+23
drivers/cpufreq/cpufreq_ondemand.h
··· 24 24 struct od_dbs_tuners { 25 25 unsigned int powersave_bias; 26 26 }; 27 + 28 + #ifdef CONFIG_X86 29 + #include <asm/cpu_device_id.h> 30 + 31 + /* 32 + * Not all CPUs want IO time to be accounted as busy; this depends on 33 + * how efficient idling at a higher frequency/voltage is. 34 + * 35 + * Pavel Machek says this is not so for various generations of AMD and 36 + * old Intel systems. Mike Chan (android.com) claims this is also not 37 + * true for ARM. 38 + * 39 + * Because of this, select a known series of Intel CPUs (Family 6 and 40 + * later) by default, and leave all others up to the user. 41 + */ 42 + static inline bool od_should_io_be_busy(void) 43 + { 44 + return (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && 45 + boot_cpu_data.x86_vfm >= INTEL_PENTIUM_PRO); 46 + } 47 + #else 48 + static inline bool od_should_io_be_busy(void) { return false; } 49 + #endif
+10 -12
drivers/cpufreq/freq_table.c
··· 28 28 return false; 29 29 } 30 30 31 - int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 32 - struct cpufreq_frequency_table *table) 31 + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy) 33 32 { 34 - struct cpufreq_frequency_table *pos; 33 + struct cpufreq_frequency_table *pos, *table = policy->freq_table; 35 34 unsigned int min_freq = ~0; 36 35 unsigned int max_freq = 0; 37 - unsigned int freq; 36 + unsigned int freq, i; 38 37 39 - cpufreq_for_each_valid_entry(pos, table) { 38 + cpufreq_for_each_valid_entry_idx(pos, table, i) { 40 39 freq = pos->frequency; 41 40 42 41 if ((!cpufreq_boost_enabled() || !policy->boost_enabled) 43 42 && (pos->flags & CPUFREQ_BOOST_FREQ)) 44 43 continue; 45 44 46 - pr_debug("table entry %u: %u kHz\n", (int)(pos - table), freq); 45 + pr_debug("table entry %u: %u kHz\n", i, freq); 47 46 if (freq < min_freq) 48 47 min_freq = freq; 49 48 if (freq > max_freq) ··· 64 65 return 0; 65 66 } 66 67 67 - int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 68 - struct cpufreq_frequency_table *table) 68 + int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy) 69 69 { 70 - struct cpufreq_frequency_table *pos; 70 + struct cpufreq_frequency_table *pos, *table = policy->freq_table; 71 71 unsigned int freq, prev_smaller = 0; 72 72 bool found = false; 73 73 ··· 108 110 if (!policy->freq_table) 109 111 return -ENODEV; 110 112 111 - return cpufreq_frequency_table_verify(policy, policy->freq_table); 113 + return cpufreq_frequency_table_verify(policy); 112 114 } 113 115 EXPORT_SYMBOL_GPL(cpufreq_generic_frequency_table_verify); 114 116 ··· 126 128 }; 127 129 struct cpufreq_frequency_table *pos; 128 130 struct cpufreq_frequency_table *table = policy->freq_table; 129 - unsigned int freq, diff, i = 0; 131 + unsigned int freq, diff, i; 130 132 int index; 131 133 132 134 pr_debug("request for target %u kHz (relation: %u) for cpu %u\n", ··· 352 354 return 0; 353 355 } 354 356 355 - ret = cpufreq_frequency_table_cpuinfo(policy, policy->freq_table); 357 + ret = cpufreq_frequency_table_cpuinfo(policy); 356 358 if (ret) 357 359 return ret; 358 360
+94 -98
drivers/cpufreq/intel_pstate.c
··· 620 620 (cpu->pstate.min_pstate * 100 / turbo_pstate) : 0; 621 621 } 622 622 623 - static s16 intel_pstate_get_epb(struct cpudata *cpu_data) 624 - { 625 - u64 epb; 626 - int ret; 627 - 628 - if (!boot_cpu_has(X86_FEATURE_EPB)) 629 - return -ENXIO; 630 - 631 - ret = rdmsrq_on_cpu(cpu_data->cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); 632 - if (ret) 633 - return (s16)ret; 634 - 635 - return (s16)(epb & 0x0f); 636 - } 637 - 638 623 static s16 intel_pstate_get_epp(struct cpudata *cpu_data, u64 hwp_req_data) 639 624 { 640 - s16 epp; 625 + s16 epp = -EOPNOTSUPP; 641 626 642 627 if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { 643 628 /* ··· 636 651 return epp; 637 652 } 638 653 epp = (hwp_req_data >> 24) & 0xff; 639 - } else { 640 - /* When there is no EPP present, HWP uses EPB settings */ 641 - epp = intel_pstate_get_epb(cpu_data); 642 654 } 643 655 644 656 return epp; 645 657 } 646 658 647 - static int intel_pstate_set_epb(int cpu, s16 pref) 648 - { 649 - u64 epb; 650 - int ret; 651 - 652 - if (!boot_cpu_has(X86_FEATURE_EPB)) 653 - return -ENXIO; 654 - 655 - ret = rdmsrq_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, &epb); 656 - if (ret) 657 - return ret; 658 - 659 - epb = (epb & ~0x0f) | pref; 660 - wrmsrq_on_cpu(cpu, MSR_IA32_ENERGY_PERF_BIAS, epb); 661 - 662 - return 0; 663 - } 664 - 665 659 /* 666 - * EPP/EPB display strings corresponding to EPP index in the 660 + * EPP display strings corresponding to EPP index in the 667 661 * energy_perf_strings[] 668 662 * index String 669 663 *------------------------------------- ··· 746 782 u32 raw_epp) 747 783 { 748 784 int epp = -EINVAL; 749 - int ret; 785 + int ret = -EOPNOTSUPP; 750 786 751 787 if (!pref_index) 752 788 epp = cpu_data->epp_default; ··· 766 802 return -EBUSY; 767 803 768 804 ret = intel_pstate_set_epp(cpu_data, epp); 769 - } else { 770 - if (epp == -EINVAL) 771 - epp = (pref_index - 1) << 2; 772 - ret = intel_pstate_set_epb(cpu_data->cpu, epp); 773 805 } 774 806 775 807 return ret; ··· 897 937 898 938 cpufreq_freq_attr_ro(base_frequency); 899 939 940 + enum hwp_cpufreq_attr_index { 941 + HWP_BASE_FREQUENCY_INDEX = 0, 942 + HWP_PERFORMANCE_PREFERENCE_INDEX, 943 + HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX, 944 + HWP_CPUFREQ_ATTR_COUNT, 945 + }; 946 + 900 947 static struct freq_attr *hwp_cpufreq_attrs[] = { 901 - &energy_performance_preference, 902 - &energy_performance_available_preferences, 903 - &base_frequency, 904 - NULL, 948 + [HWP_BASE_FREQUENCY_INDEX] = &base_frequency, 949 + [HWP_PERFORMANCE_PREFERENCE_INDEX] = &energy_performance_preference, 950 + [HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX] = 951 + &energy_performance_available_preferences, 952 + [HWP_CPUFREQ_ATTR_COUNT] = NULL, 905 953 }; 906 954 907 955 static bool no_cas __ro_after_init; ··· 1305 1337 if (boot_cpu_has(X86_FEATURE_HWP_EPP)) { 1306 1338 value &= ~GENMASK_ULL(31, 24); 1307 1339 value |= (u64)epp << 24; 1308 - } else { 1309 - intel_pstate_set_epb(cpu, epp); 1310 1340 } 1341 + 1311 1342 skip_epp: 1312 1343 WRITE_ONCE(cpu_data->hwp_req_cached, value); 1313 1344 wrmsrq_on_cpu(cpu, MSR_HWP_REQUEST, value); ··· 1377 1410 1378 1411 #define POWER_CTL_EE_ENABLE 1 1379 1412 #define POWER_CTL_EE_DISABLE 2 1413 + 1414 + /* Enable bit for Dynamic Efficiency Control (DEC) */ 1415 + #define POWER_CTL_DEC_ENABLE 27 1380 1416 1381 1417 static int power_ctl_ee_state; 1382 1418 ··· 1472 1502 1473 1503 static bool intel_pstate_update_max_freq(struct cpudata *cpudata) 1474 1504 { 1475 - struct cpufreq_policy *policy __free(put_cpufreq_policy); 1476 - 1477 - policy = cpufreq_cpu_get(cpudata->cpu); 1505 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpudata->cpu); 1478 1506 if (!policy) 1479 1507 return false; 1480 1508 ··· 1663 1695 return count; 1664 1696 } 1665 1697 1666 - static void update_qos_request(enum freq_qos_req_type type) 1698 + static void update_cpu_qos_request(int cpu, enum freq_qos_req_type type) 1667 1699 { 1700 + struct cpudata *cpudata = all_cpu_data[cpu]; 1701 + unsigned int freq = cpudata->pstate.turbo_freq; 1668 1702 struct freq_qos_request *req; 1669 - struct cpufreq_policy *policy; 1703 + 1704 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 1705 + if (!policy) 1706 + return; 1707 + 1708 + req = policy->driver_data; 1709 + if (!req) 1710 + return; 1711 + 1712 + if (hwp_active) 1713 + intel_pstate_get_hwp_cap(cpudata); 1714 + 1715 + if (type == FREQ_QOS_MIN) { 1716 + freq = DIV_ROUND_UP(freq * global.min_perf_pct, 100); 1717 + } else { 1718 + req++; 1719 + freq = (freq * global.max_perf_pct) / 100; 1720 + } 1721 + 1722 + if (freq_qos_update_request(req, freq) < 0) 1723 + pr_warn("Failed to update freq constraint: CPU%d\n", cpu); 1724 + } 1725 + 1726 + static void update_qos_requests(enum freq_qos_req_type type) 1727 + { 1670 1728 int i; 1671 1729 1672 - for_each_possible_cpu(i) { 1673 - struct cpudata *cpu = all_cpu_data[i]; 1674 - unsigned int freq, perf_pct; 1675 - 1676 - policy = cpufreq_cpu_get(i); 1677 - if (!policy) 1678 - continue; 1679 - 1680 - req = policy->driver_data; 1681 - cpufreq_cpu_put(policy); 1682 - 1683 - if (!req) 1684 - continue; 1685 - 1686 - if (hwp_active) 1687 - intel_pstate_get_hwp_cap(cpu); 1688 - 1689 - if (type == FREQ_QOS_MIN) { 1690 - perf_pct = global.min_perf_pct; 1691 - } else { 1692 - req++; 1693 - perf_pct = global.max_perf_pct; 1694 - } 1695 - 1696 - freq = DIV_ROUND_UP(cpu->pstate.turbo_freq * perf_pct, 100); 1697 - 1698 - if (freq_qos_update_request(req, freq) < 0) 1699 - pr_warn("Failed to update freq constraint: CPU%d\n", i); 1700 - } 1730 + for_each_possible_cpu(i) 1731 + update_cpu_qos_request(i, type); 1701 1732 } 1702 1733 1703 1734 static ssize_t store_max_perf_pct(struct kobject *a, struct kobj_attribute *b, ··· 1725 1758 if (intel_pstate_driver == &intel_pstate) 1726 1759 intel_pstate_update_policies(); 1727 1760 else 1728 - update_qos_request(FREQ_QOS_MAX); 1761 + update_qos_requests(FREQ_QOS_MAX); 1729 1762 1730 1763 mutex_unlock(&intel_pstate_driver_lock); 1731 1764 ··· 1759 1792 if (intel_pstate_driver == &intel_pstate) 1760 1793 intel_pstate_update_policies(); 1761 1794 else 1762 - update_qos_request(FREQ_QOS_MIN); 1795 + update_qos_requests(FREQ_QOS_MIN); 1763 1796 1764 1797 mutex_unlock(&intel_pstate_driver_lock); 1765 1798 ··· 2542 2575 * that sample.time will always be reset before setting the utilization 2543 2576 * update hook and make the caller skip the sample then. 2544 2577 */ 2545 - if (cpu->last_sample_time) { 2578 + if (likely(cpu->last_sample_time)) { 2546 2579 intel_pstate_calc_avg_perf(cpu); 2547 2580 return true; 2548 2581 } ··· 3769 3802 {} 3770 3803 }; 3771 3804 3805 + static bool hwp_check_epp(void) 3806 + { 3807 + if (boot_cpu_has(X86_FEATURE_HWP_EPP)) 3808 + return true; 3809 + 3810 + /* Without EPP support, don't expose EPP-related sysfs attributes. */ 3811 + hwp_cpufreq_attrs[HWP_PERFORMANCE_PREFERENCE_INDEX] = NULL; 3812 + hwp_cpufreq_attrs[HWP_PERFORMANCE_AVAILABLE_PREFERENCES_INDEX] = NULL; 3813 + 3814 + return false; 3815 + } 3816 + 3817 + static bool hwp_check_dec(void) 3818 + { 3819 + u64 power_ctl; 3820 + 3821 + rdmsrq(MSR_IA32_POWER_CTL, power_ctl); 3822 + return !!(power_ctl & BIT(POWER_CTL_DEC_ENABLE)); 3823 + } 3824 + 3772 3825 static int __init intel_pstate_init(void) 3773 3826 { 3774 3827 static struct cpudata **_all_cpu_data; ··· 3809 3822 3810 3823 id = x86_match_cpu(hwp_support_ids); 3811 3824 if (id) { 3812 - hwp_forced = intel_pstate_hwp_is_enabled(); 3825 + bool epp_present = hwp_check_epp(); 3813 3826 3814 - if (hwp_forced) 3827 + /* 3828 + * If HWP is enabled already, there is no choice but to deal 3829 + * with it. 3830 + */ 3831 + hwp_forced = intel_pstate_hwp_is_enabled(); 3832 + if (hwp_forced) { 3815 3833 pr_info("HWP enabled by BIOS\n"); 3816 - else if (no_load) 3834 + no_hwp = 0; 3835 + } else if (no_load) { 3817 3836 return -ENODEV; 3837 + } else if (!epp_present && !hwp_check_dec()) { 3838 + /* 3839 + * Avoid enabling HWP for processors without EPP support 3840 + * unless the Dynamic Efficiency Control (DEC) enable 3841 + * bit (MSR_IA32_POWER_CTL, bit 27) is set because that 3842 + * means incomplete HWP implementation which is a corner 3843 + * case and supporting it is generally problematic. 3844 + */ 3845 + no_hwp = 1; 3846 + } 3818 3847 3819 3848 copy_cpu_funcs(&core_funcs); 3820 - /* 3821 - * Avoid enabling HWP for processors without EPP support, 3822 - * because that means incomplete HWP implementation which is a 3823 - * corner case and supporting it is generally problematic. 3824 - * 3825 - * If HWP is enabled already, though, there is no choice but to 3826 - * deal with it. 3827 - */ 3828 - if ((!no_hwp && boot_cpu_has(X86_FEATURE_HWP_EPP)) || hwp_forced) { 3849 + 3850 + if (!no_hwp) { 3829 3851 hwp_active = true; 3830 3852 hwp_mode_bdw = id->driver_data; 3831 3853 intel_pstate.attr = hwp_cpufreq_attrs;
+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 }
+2 -4
drivers/cpufreq/sh-cpufreq.c
··· 89 89 static int sh_cpufreq_verify(struct cpufreq_policy_data *policy) 90 90 { 91 91 struct clk *cpuclk = &per_cpu(sh_cpuclk, policy->cpu); 92 - struct cpufreq_frequency_table *freq_table; 93 92 94 - freq_table = cpuclk->nr_freqs ? cpuclk->freq_table : NULL; 95 - if (freq_table) 96 - return cpufreq_frequency_table_verify(policy, freq_table); 93 + if (policy->freq_table) 94 + return cpufreq_frequency_table_verify(policy); 97 95 98 96 cpufreq_verify_within_cpu_limits(policy); 99 97
+6 -6
drivers/cpufreq/speedstep-lib.c
··· 378 378 * DETECT SPEEDSTEP SPEEDS * 379 379 *********************************************************************/ 380 380 381 - unsigned int speedstep_get_freqs(enum speedstep_processor processor, 382 - unsigned int *low_speed, 383 - unsigned int *high_speed, 384 - unsigned int *transition_latency, 385 - void (*set_state) (unsigned int state)) 381 + int speedstep_get_freqs(enum speedstep_processor processor, 382 + unsigned int *low_speed, 383 + unsigned int *high_speed, 384 + unsigned int *transition_latency, 385 + void (*set_state)(unsigned int state)) 386 386 { 387 387 unsigned int prev_speed; 388 - unsigned int ret = 0; 389 388 unsigned long flags; 390 389 ktime_t tv1, tv2; 390 + int ret = 0; 391 391 392 392 if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) 393 393 return -EINVAL;
+5 -5
drivers/cpufreq/speedstep-lib.h
··· 41 41 * SPEEDSTEP_LOW; the second argument is zero so that no 42 42 * cpufreq_notify_transition calls are initiated. 43 43 */ 44 - extern unsigned int speedstep_get_freqs(enum speedstep_processor processor, 45 - unsigned int *low_speed, 46 - unsigned int *high_speed, 47 - unsigned int *transition_latency, 48 - void (*set_state) (unsigned int state)); 44 + extern int speedstep_get_freqs(enum speedstep_processor processor, 45 + unsigned int *low_speed, 46 + unsigned int *high_speed, 47 + unsigned int *transition_latency, 48 + void (*set_state)(unsigned int state));
+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
drivers/cpufreq/virtual-cpufreq.c
··· 250 250 static int virt_cpufreq_verify_policy(struct cpufreq_policy_data *policy) 251 251 { 252 252 if (policy->freq_table) 253 - return cpufreq_frequency_table_verify(policy, policy->freq_table); 253 + return cpufreq_frequency_table_verify(policy); 254 254 255 255 cpufreq_verify_within_cpu_limits(policy); 256 256 return 0;
+3 -4
include/linux/cpufreq.h
··· 780 780 else 781 781 782 782 783 - int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, 784 - struct cpufreq_frequency_table *table); 783 + int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy); 785 784 786 - int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy, 787 - struct cpufreq_frequency_table *table); 785 + int cpufreq_frequency_table_verify(struct cpufreq_policy_data *policy); 786 + 788 787 int cpufreq_generic_frequency_table_verify(struct cpufreq_policy_data *policy); 789 788 790 789 int cpufreq_table_index_unsorted(struct cpufreq_policy *policy,
+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)?;