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

Merge branch 'pm-cpufreq'

* pm-cpufreq:
cpufreq: Fix up cpufreq_boost_set_sw()
cpufreq: fix minor typo in struct cpufreq_driver doc comment
cpufreq: qoriq: Add platform dependencies
clk: qoriq: add cpufreq platform device
cpufreq: qoriq: convert to a platform driver
cpufreq: qcom: fix wrong compatible binding
cpufreq: imx-cpufreq-dt: support i.MX7ULP
cpufreq: dt: Add support for r8a7742
cpufreq: Add i.MX7ULP to cpufreq-dt-platdev blacklist
cpufreq: omap: Build driver by default for ARCH_OMAP2PLUS
cpufreq: intel_pstate: Use passive mode by default without HWP

+173 -75
+19 -13
Documentation/admin-guide/pm/intel_pstate.rst
··· 62 62 Active Mode 63 63 ----------- 64 64 65 - This is the default operation mode of ``intel_pstate``. If it works in this 66 - mode, the ``scaling_driver`` policy attribute in ``sysfs`` for all ``CPUFreq`` 67 - policies contains the string "intel_pstate". 65 + This is the default operation mode of ``intel_pstate`` for processors with 66 + hardware-managed P-states (HWP) support. If it works in this mode, the 67 + ``scaling_driver`` policy attribute in ``sysfs`` for all ``CPUFreq`` policies 68 + contains the string "intel_pstate". 68 69 69 70 In this mode the driver bypasses the scaling governors layer of ``CPUFreq`` and 70 71 provides its own scaling algorithms for P-state selection. Those algorithms ··· 139 138 Active Mode Without HWP 140 139 ~~~~~~~~~~~~~~~~~~~~~~~ 141 140 142 - This is the default operation mode for processors that do not support the HWP 143 - feature. It also is used by default with the ``intel_pstate=no_hwp`` argument 144 - in the kernel command line. However, in this mode ``intel_pstate`` may refuse 145 - to work with the given processor if it does not recognize it. [Note that 146 - ``intel_pstate`` will never refuse to work with any processor with the HWP 147 - feature enabled.] 141 + This operation mode is optional for processors that do not support the HWP 142 + feature or when the ``intel_pstate=no_hwp`` argument is passed to the kernel in 143 + the command line. The active mode is used in those cases if the 144 + ``intel_pstate=active`` argument is passed to the kernel in the command line. 145 + In this mode ``intel_pstate`` may refuse to work with processors that are not 146 + recognized by it. [Note that ``intel_pstate`` will never refuse to work with 147 + any processor with the HWP feature enabled.] 148 148 149 149 In this mode ``intel_pstate`` registers utilization update callbacks with the 150 150 CPU scheduler in order to run a P-state selection algorithm, either ··· 190 188 Passive Mode 191 189 ------------ 192 190 193 - This mode is used if the ``intel_pstate=passive`` argument is passed to the 194 - kernel in the command line (it implies the ``intel_pstate=no_hwp`` setting too). 195 - Like in the active mode without HWP support, in this mode ``intel_pstate`` may 196 - refuse to work with the given processor if it does not recognize it. 191 + This is the default operation mode of ``intel_pstate`` for processors without 192 + hardware-managed P-states (HWP) support. It is always used if the 193 + ``intel_pstate=passive`` argument is passed to the kernel in the command line 194 + regardless of whether or not the given processor supports HWP. [Note that the 195 + ``intel_pstate=no_hwp`` setting implies ``intel_pstate=passive`` if it is used 196 + without ``intel_pstate=active``.] Like in the active mode without HWP support, 197 + in this mode ``intel_pstate`` may refuse to work with processors that are not 198 + recognized by it. 197 199 198 200 If the driver works in this mode, the ``scaling_driver`` policy attribute in 199 201 ``sysfs`` for all ``CPUFreq`` policies contains the string "intel_cpufreq".
+27 -3
drivers/clk/clk-qoriq.c
··· 95 95 }; 96 96 97 97 static struct clockgen clockgen; 98 + static bool add_cpufreq_dev __initdata; 98 99 99 100 static void cg_out(struct clockgen *cg, u32 val, u32 __iomem *reg) 100 101 { ··· 1020 1019 } 1021 1020 } 1022 1021 1023 - static void __init clockgen_init(struct device_node *np); 1022 + static void __init _clockgen_init(struct device_node *np, bool legacy); 1024 1023 1025 1024 /* 1026 1025 * Legacy nodes may get probed before the parent clockgen node. ··· 1031 1030 static void __init legacy_init_clockgen(struct device_node *np) 1032 1031 { 1033 1032 if (!clockgen.node) 1034 - clockgen_init(of_get_parent(np)); 1033 + _clockgen_init(of_get_parent(np), true); 1035 1034 } 1036 1035 1037 1036 /* Legacy node */ ··· 1448 1447 } 1449 1448 #endif 1450 1449 1451 - static void __init clockgen_init(struct device_node *np) 1450 + static void __init _clockgen_init(struct device_node *np, bool legacy) 1452 1451 { 1453 1452 int i, ret; 1454 1453 bool is_old_ls1021a = false; ··· 1517 1516 __func__, np, ret); 1518 1517 } 1519 1518 1519 + /* Don't create cpufreq device for legacy clockgen blocks */ 1520 + add_cpufreq_dev = !legacy; 1521 + 1520 1522 return; 1521 1523 err: 1522 1524 iounmap(clockgen.regs); 1523 1525 clockgen.regs = NULL; 1524 1526 } 1527 + 1528 + static void __init clockgen_init(struct device_node *np) 1529 + { 1530 + _clockgen_init(np, false); 1531 + } 1532 + 1533 + static int __init clockgen_cpufreq_init(void) 1534 + { 1535 + struct platform_device *pdev; 1536 + 1537 + if (add_cpufreq_dev) { 1538 + pdev = platform_device_register_simple("qoriq-cpufreq", -1, 1539 + NULL, 0); 1540 + if (IS_ERR(pdev)) 1541 + pr_err("Couldn't register qoriq-cpufreq err=%ld\n", 1542 + PTR_ERR(pdev)); 1543 + } 1544 + return 0; 1545 + } 1546 + device_initcall(clockgen_cpufreq_init); 1525 1547 1526 1548 CLK_OF_DECLARE(qoriq_clockgen_1, "fsl,qoriq-clockgen-1.0", clockgen_init); 1527 1549 CLK_OF_DECLARE(qoriq_clockgen_2, "fsl,qoriq-clockgen-2.0", clockgen_init);
+2 -1
drivers/cpufreq/Kconfig
··· 323 323 324 324 config QORIQ_CPUFREQ 325 325 tristate "CPU frequency scaling driver for Freescale QorIQ SoCs" 326 - depends on OF && COMMON_CLK && (PPC_E500MC || ARM || ARM64) 326 + depends on OF && COMMON_CLK 327 + depends on PPC_E500MC || SOC_LS1021A || ARCH_LAYERSCAPE || COMPILE_TEST 327 328 select CLK_QORIQ 328 329 help 329 330 This adds the CPUFreq driver support for Freescale QorIQ SoCs
+1
drivers/cpufreq/Kconfig.arm
··· 317 317 config ARM_TI_CPUFREQ 318 318 bool "Texas Instruments CPUFreq support" 319 319 depends on ARCH_OMAP2PLUS 320 + default ARCH_OMAP2PLUS 320 321 help 321 322 This driver enables valid OPPs on the running platform based on 322 323 values contained within the SoC in use. Enable this in order to
+2
drivers/cpufreq/cpufreq-dt-platdev.c
··· 53 53 { .compatible = "renesas,r7s72100", }, 54 54 { .compatible = "renesas,r8a73a4", }, 55 55 { .compatible = "renesas,r8a7740", }, 56 + { .compatible = "renesas,r8a7742", }, 56 57 { .compatible = "renesas,r8a7743", }, 57 58 { .compatible = "renesas,r8a7744", }, 58 59 { .compatible = "renesas,r8a7745", }, ··· 106 105 { .compatible = "calxeda,highbank", }, 107 106 { .compatible = "calxeda,ecx-2000", }, 108 107 108 + { .compatible = "fsl,imx7ulp", }, 109 109 { .compatible = "fsl,imx7d", }, 110 110 { .compatible = "fsl,imx8mq", }, 111 111 { .compatible = "fsl,imx8mm", },
+6 -5
drivers/cpufreq/cpufreq.c
··· 2535 2535 static int cpufreq_boost_set_sw(int state) 2536 2536 { 2537 2537 struct cpufreq_policy *policy; 2538 - int ret = -EINVAL; 2539 2538 2540 2539 for_each_active_policy(policy) { 2540 + int ret; 2541 + 2541 2542 if (!policy->freq_table) 2542 - continue; 2543 + return -ENXIO; 2543 2544 2544 2545 ret = cpufreq_frequency_table_cpuinfo(policy, 2545 2546 policy->freq_table); 2546 2547 if (ret) { 2547 2548 pr_err("%s: Policy frequency update failed\n", 2548 2549 __func__); 2549 - break; 2550 + return ret; 2550 2551 } 2551 2552 2552 2553 ret = freq_qos_update_request(policy->max_freq_req, policy->max); 2553 2554 if (ret < 0) 2554 - break; 2555 + return ret; 2555 2556 } 2556 2557 2557 - return ret; 2558 + return 0; 2558 2559 } 2559 2560 2560 2561 int cpufreq_boost_trigger_state(int state)
+82 -2
drivers/cpufreq/imx-cpufreq-dt.c
··· 3 3 * Copyright 2019 NXP 4 4 */ 5 5 6 + #include <linux/clk.h> 6 7 #include <linux/cpu.h> 8 + #include <linux/cpufreq.h> 7 9 #include <linux/err.h> 8 10 #include <linux/init.h> 9 11 #include <linux/kernel.h> ··· 14 12 #include <linux/of.h> 15 13 #include <linux/platform_device.h> 16 14 #include <linux/pm_opp.h> 15 + #include <linux/regulator/consumer.h> 17 16 #include <linux/slab.h> 17 + 18 + #include "cpufreq-dt.h" 18 19 19 20 #define OCOTP_CFG3_SPEED_GRADE_SHIFT 8 20 21 #define OCOTP_CFG3_SPEED_GRADE_MASK (0x3 << 8) ··· 27 22 #define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_SHIFT 5 28 23 #define IMX8MP_OCOTP_CFG3_MKT_SEGMENT_MASK (0x3 << 5) 29 24 25 + #define IMX7ULP_MAX_RUN_FREQ 528000 26 + 30 27 /* cpufreq-dt device registered by imx-cpufreq-dt */ 31 28 static struct platform_device *cpufreq_dt_pdev; 32 29 static struct opp_table *cpufreq_opp_table; 30 + static struct device *cpu_dev; 31 + 32 + enum IMX7ULP_CPUFREQ_CLKS { 33 + ARM, 34 + CORE, 35 + SCS_SEL, 36 + HSRUN_CORE, 37 + HSRUN_SCS_SEL, 38 + FIRC, 39 + }; 40 + 41 + static struct clk_bulk_data imx7ulp_clks[] = { 42 + { .id = "arm" }, 43 + { .id = "core" }, 44 + { .id = "scs_sel" }, 45 + { .id = "hsrun_core" }, 46 + { .id = "hsrun_scs_sel" }, 47 + { .id = "firc" }, 48 + }; 49 + 50 + static unsigned int imx7ulp_get_intermediate(struct cpufreq_policy *policy, 51 + unsigned int index) 52 + { 53 + return clk_get_rate(imx7ulp_clks[FIRC].clk); 54 + } 55 + 56 + static int imx7ulp_target_intermediate(struct cpufreq_policy *policy, 57 + unsigned int index) 58 + { 59 + unsigned int newfreq = policy->freq_table[index].frequency; 60 + 61 + clk_set_parent(imx7ulp_clks[SCS_SEL].clk, imx7ulp_clks[FIRC].clk); 62 + clk_set_parent(imx7ulp_clks[HSRUN_SCS_SEL].clk, imx7ulp_clks[FIRC].clk); 63 + 64 + if (newfreq > IMX7ULP_MAX_RUN_FREQ) 65 + clk_set_parent(imx7ulp_clks[ARM].clk, 66 + imx7ulp_clks[HSRUN_CORE].clk); 67 + else 68 + clk_set_parent(imx7ulp_clks[ARM].clk, imx7ulp_clks[CORE].clk); 69 + 70 + return 0; 71 + } 72 + 73 + static struct cpufreq_dt_platform_data imx7ulp_data = { 74 + .target_intermediate = imx7ulp_target_intermediate, 75 + .get_intermediate = imx7ulp_get_intermediate, 76 + }; 33 77 34 78 static int imx_cpufreq_dt_probe(struct platform_device *pdev) 35 79 { 36 - struct device *cpu_dev = get_cpu_device(0); 80 + struct platform_device *dt_pdev; 37 81 u32 cell_value, supported_hw[2]; 38 82 int speed_grade, mkt_segment; 39 83 int ret; 40 84 85 + cpu_dev = get_cpu_device(0); 86 + 41 87 if (!of_find_property(cpu_dev->of_node, "cpu-supply", NULL)) 42 88 return -ENODEV; 89 + 90 + if (of_machine_is_compatible("fsl,imx7ulp")) { 91 + ret = clk_bulk_get(cpu_dev, ARRAY_SIZE(imx7ulp_clks), 92 + imx7ulp_clks); 93 + if (ret) 94 + return ret; 95 + 96 + dt_pdev = platform_device_register_data(NULL, "cpufreq-dt", 97 + -1, &imx7ulp_data, 98 + sizeof(imx7ulp_data)); 99 + if (IS_ERR(dt_pdev)) { 100 + clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks); 101 + ret = PTR_ERR(dt_pdev); 102 + dev_err(&pdev->dev, "Failed to register cpufreq-dt: %d\n", ret); 103 + return ret; 104 + } 105 + 106 + cpufreq_dt_pdev = dt_pdev; 107 + 108 + return 0; 109 + } 43 110 44 111 ret = nvmem_cell_read_u32(cpu_dev, "speed_grade", &cell_value); 45 112 if (ret) ··· 175 98 static int imx_cpufreq_dt_remove(struct platform_device *pdev) 176 99 { 177 100 platform_device_unregister(cpufreq_dt_pdev); 178 - dev_pm_opp_put_supported_hw(cpufreq_opp_table); 101 + if (!of_machine_is_compatible("fsl,imx7ulp")) 102 + dev_pm_opp_put_supported_hw(cpufreq_opp_table); 103 + else 104 + clk_bulk_put(ARRAY_SIZE(imx7ulp_clks), imx7ulp_clks); 179 105 180 106 return 0; 181 107 }
+2 -1
drivers/cpufreq/intel_pstate.c
··· 2771 2771 pr_info("Invalid MSRs\n"); 2772 2772 return -ENODEV; 2773 2773 } 2774 + /* Without HWP start in the passive mode. */ 2775 + default_driver = &intel_cpufreq; 2774 2776 2775 2777 hwp_cpu_matched: 2776 2778 /* ··· 2818 2816 if (!strcmp(str, "disable")) { 2819 2817 no_load = 1; 2820 2818 } else if (!strcmp(str, "passive")) { 2821 - pr_info("Passive mode enabled\n"); 2822 2819 default_driver = &intel_cpufreq; 2823 2820 no_hwp = 1; 2824 2821 }
+1 -1
drivers/cpufreq/qcom-cpufreq-nvmem.c
··· 277 277 if (!np) 278 278 return -ENOENT; 279 279 280 - ret = of_device_is_compatible(np, "operating-points-v2-qcom-cpu"); 280 + ret = of_device_is_compatible(np, "operating-points-v2-kryo-cpu"); 281 281 if (!ret) { 282 282 of_node_put(np); 283 283 return -ENOENT;
+30 -48
drivers/cpufreq/qoriq-cpufreq.c
··· 18 18 #include <linux/of.h> 19 19 #include <linux/slab.h> 20 20 #include <linux/smp.h> 21 + #include <linux/platform_device.h> 21 22 22 23 /** 23 24 * struct cpu_data ··· 29 28 struct clk **pclk; 30 29 struct cpufreq_frequency_table *table; 31 30 }; 32 - 33 - /* 34 - * Don't use cpufreq on this SoC -- used when the SoC would have otherwise 35 - * matched a more generic compatible. 36 - */ 37 - #define SOC_BLACKLIST 1 38 31 39 32 /** 40 33 * struct soc_data - SoC specific data ··· 259 264 .attr = cpufreq_generic_attr, 260 265 }; 261 266 262 - static const struct soc_data blacklist = { 263 - .flags = SOC_BLACKLIST, 264 - }; 265 - 266 - static const struct of_device_id node_matches[] __initconst = { 267 + static const struct of_device_id qoriq_cpufreq_blacklist[] = { 267 268 /* e6500 cannot use cpufreq due to erratum A-008083 */ 268 - { .compatible = "fsl,b4420-clockgen", &blacklist }, 269 - { .compatible = "fsl,b4860-clockgen", &blacklist }, 270 - { .compatible = "fsl,t2080-clockgen", &blacklist }, 271 - { .compatible = "fsl,t4240-clockgen", &blacklist }, 272 - 273 - { .compatible = "fsl,ls1012a-clockgen", }, 274 - { .compatible = "fsl,ls1021a-clockgen", }, 275 - { .compatible = "fsl,ls1028a-clockgen", }, 276 - { .compatible = "fsl,ls1043a-clockgen", }, 277 - { .compatible = "fsl,ls1046a-clockgen", }, 278 - { .compatible = "fsl,ls1088a-clockgen", }, 279 - { .compatible = "fsl,ls2080a-clockgen", }, 280 - { .compatible = "fsl,lx2160a-clockgen", }, 281 - { .compatible = "fsl,p4080-clockgen", }, 282 - { .compatible = "fsl,qoriq-clockgen-1.0", }, 283 - { .compatible = "fsl,qoriq-clockgen-2.0", }, 269 + { .compatible = "fsl,b4420-clockgen", }, 270 + { .compatible = "fsl,b4860-clockgen", }, 271 + { .compatible = "fsl,t2080-clockgen", }, 272 + { .compatible = "fsl,t4240-clockgen", }, 284 273 {} 285 274 }; 286 275 287 - static int __init qoriq_cpufreq_init(void) 276 + static int qoriq_cpufreq_probe(struct platform_device *pdev) 288 277 { 289 278 int ret; 290 - struct device_node *np; 291 - const struct of_device_id *match; 292 - const struct soc_data *data; 279 + struct device_node *np; 293 280 294 - np = of_find_matching_node(NULL, node_matches); 295 - if (!np) 281 + np = of_find_matching_node(NULL, qoriq_cpufreq_blacklist); 282 + if (np) { 283 + dev_info(&pdev->dev, "Disabling due to erratum A-008083"); 296 284 return -ENODEV; 297 - 298 - match = of_match_node(node_matches, np); 299 - data = match->data; 300 - 301 - of_node_put(np); 302 - 303 - if (data && data->flags & SOC_BLACKLIST) 304 - return -ENODEV; 285 + } 305 286 306 287 ret = cpufreq_register_driver(&qoriq_cpufreq_driver); 307 - if (!ret) 308 - pr_info("Freescale QorIQ CPU frequency scaling driver\n"); 288 + if (ret) 289 + return ret; 309 290 310 - return ret; 291 + dev_info(&pdev->dev, "Freescale QorIQ CPU frequency scaling driver\n"); 292 + return 0; 311 293 } 312 - module_init(qoriq_cpufreq_init); 313 294 314 - static void __exit qoriq_cpufreq_exit(void) 295 + static int qoriq_cpufreq_remove(struct platform_device *pdev) 315 296 { 316 297 cpufreq_unregister_driver(&qoriq_cpufreq_driver); 317 - } 318 - module_exit(qoriq_cpufreq_exit); 319 298 299 + return 0; 300 + } 301 + 302 + static struct platform_driver qoriq_cpufreq_platform_driver = { 303 + .driver = { 304 + .name = "qoriq-cpufreq", 305 + }, 306 + .probe = qoriq_cpufreq_probe, 307 + .remove = qoriq_cpufreq_remove, 308 + }; 309 + module_platform_driver(qoriq_cpufreq_platform_driver); 310 + 311 + MODULE_ALIAS("platform:qoriq-cpufreq"); 320 312 MODULE_LICENSE("GPL"); 321 313 MODULE_AUTHOR("Tang Yuantian <Yuantian.Tang@freescale.com>"); 322 314 MODULE_DESCRIPTION("cpufreq driver for Freescale QorIQ series SoCs");
+1 -1
include/linux/cpufreq.h
··· 330 330 * 331 331 * get_intermediate should return a stable intermediate frequency 332 332 * platform wants to switch to and target_intermediate() should set CPU 333 - * to to that frequency, before jumping to the frequency corresponding 333 + * to that frequency, before jumping to the frequency corresponding 334 334 * to 'index'. Core will take care of sending notifications and driver 335 335 * doesn't have to handle them in target_intermediate() or 336 336 * target_index().