OSDN Git Service

kernel: bump 5.15 to 5.15.32
[immortalwrt/immortalwrt.git] / target / linux / ipq806x / patches-5.15 / 098-3-add-fab-scaling-support-with-cpufreq.patch
1 --- a/drivers/clk/qcom/Makefile
2 +++ b/drivers/clk/qcom/Makefile
3 @@ -15,6 +15,7 @@ clk-qcom-$(CONFIG_KRAIT_CLOCKS) += clk-k
4  clk-qcom-y += clk-hfpll.o
5  clk-qcom-y += reset.o
6  clk-qcom-$(CONFIG_QCOM_GDSC) += gdsc.o
7 +clk-qcom-y += fab_scaling.o
8  
9  # Keep alphabetically sorted by config
10  obj-$(CONFIG_APQ_GCC_8084) += gcc-apq8084.o
11 --- /dev/null
12 +++ b/drivers/clk/qcom/fab_scaling.c
13 @@ -0,0 +1,172 @@
14 +/*
15 + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
16 + *
17 + * Permission to use, copy, modify, and/or distribute this software for any
18 + * purpose with or without fee is hereby granted, provided that the above
19 + * copyright notice and this permission notice appear in all copies.
20 + *
21 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
22 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
23 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
24 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
25 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
26 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
27 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
28 + */
29 +
30 +#include <linux/kernel.h>
31 +#include <linux/init.h>
32 +#include <linux/module.h>
33 +#include <linux/platform_device.h>
34 +#include <linux/err.h>
35 +#include <linux/io.h>
36 +#include <linux/of.h>
37 +#include <linux/of_device.h>
38 +#include <linux/clk.h>
39 +#include <linux/clk-provider.h>
40 +#include <linux/slab.h>
41 +#include <linux/fab_scaling.h>
42 +
43 +struct qcom_fab_scaling_data {
44 +       u32 fab_freq_high;
45 +       u32 fab_freq_nominal;
46 +       u32 cpu_freq_threshold;
47 +       struct clk *apps_fab_clk;
48 +       struct clk *ddr_fab_clk;
49 +};
50 +
51 +static struct qcom_fab_scaling_data *drv_data;
52 +
53 +int scale_fabrics(unsigned long max_cpu_freq)
54 +{      
55 +       struct clk *apps_fab_clk = drv_data->apps_fab_clk,
56 +                  *ddr_fab_clk = drv_data->ddr_fab_clk;
57 +       unsigned long target_freq, cur_freq;
58 +       int ret;
59 +
60 +       /* Skip fab scaling if the driver is not ready */
61 +       if (!apps_fab_clk || !ddr_fab_clk)
62 +               return 0;
63 +
64 +       if (max_cpu_freq > drv_data->cpu_freq_threshold)
65 +               target_freq = drv_data->fab_freq_high;
66 +       else
67 +               target_freq = drv_data->fab_freq_nominal;
68 +
69 +       cur_freq = clk_get_rate(ddr_fab_clk);
70 +
71 +       if (target_freq != cur_freq) {
72 +               ret = clk_set_rate(apps_fab_clk, target_freq);
73 +               if (ret)
74 +                       return ret;
75 +               ret = clk_set_rate(ddr_fab_clk, target_freq);
76 +               if (ret)
77 +                       return ret;
78 +       }
79 +
80 +       return 0;
81 +}
82 +EXPORT_SYMBOL(scale_fabrics);
83 +
84 +static int ipq806x_fab_scaling_probe(struct platform_device *pdev)
85 +{
86 +       struct device_node *np = pdev->dev.of_node;
87 +       struct clk *apps_fab_clk, *ddr_fab_clk;
88 +       int ret;
89 +
90 +       if (!np)
91 +               return -ENODEV;
92 +       
93 +       drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
94 +       if (!drv_data)
95 +               return -ENOMEM;
96 +
97 +       if (of_property_read_u32(np, "fab_freq_high", &drv_data->fab_freq_high)) {
98 +               pr_err("FABRICS turbo freq not found. Using defaults...\n");
99 +               drv_data->fab_freq_high = 533000000;
100 +       }
101 +
102 +       if (of_property_read_u32(np, "fab_freq_nominal", &drv_data->fab_freq_nominal)) {
103 +               pr_err("FABRICS nominal freq not found. Using defaults...\n");
104 +               drv_data->fab_freq_nominal = 400000000;
105 +       }
106 +
107 +       if (of_property_read_u32(np, "cpu_freq_threshold", &drv_data->cpu_freq_threshold)) {
108 +               pr_err("FABRICS cpu freq threshold not found. Using defaults...\n");
109 +               drv_data->cpu_freq_threshold = 1000000000;
110 +       }
111 +
112 +       apps_fab_clk = devm_clk_get(&pdev->dev, "apps-fab-clk");
113 +       ret = PTR_ERR_OR_ZERO(apps_fab_clk);
114 +       if (ret) {
115 +               /*
116 +                * If apps fab clk node is present, but clock is not yet
117 +                * registered, we should try defering probe.
118 +                */
119 +               if (ret != -EPROBE_DEFER) {
120 +                       pr_err("Failed to get APPS FABRIC clock: %d\n", ret);
121 +                       ret = -ENODEV;
122 +               }
123 +               goto err;
124 +       }
125 +
126 +       clk_prepare_enable(apps_fab_clk);
127 +       clk_set_rate(apps_fab_clk, drv_data->fab_freq_high);
128 +       drv_data->apps_fab_clk = apps_fab_clk;
129 +
130 +       ddr_fab_clk = devm_clk_get(&pdev->dev, "ddr-fab-clk");
131 +       ret = PTR_ERR_OR_ZERO(ddr_fab_clk);
132 +       if (ret) {
133 +               /*
134 +                * If ddr fab clk node is present, but clock is not yet
135 +                * registered, we should try defering probe.
136 +                */
137 +               if (ret != -EPROBE_DEFER) {
138 +                       pr_err("Failed to get DDR FABRIC clock: %d\n", ret);
139 +                       ddr_fab_clk = NULL;
140 +                       ret = -ENODEV;
141 +               }
142 +               goto err;
143 +       }
144 +
145 +       clk_prepare_enable(ddr_fab_clk);
146 +       clk_set_rate(ddr_fab_clk, drv_data->fab_freq_high);
147 +       drv_data->ddr_fab_clk = ddr_fab_clk;
148 +
149 +       return 0;
150 +err:
151 +       kfree(drv_data);
152 +       return ret;
153 +}
154 +
155 +static int ipq806x_fab_scaling_remove(struct platform_device *pdev)
156 +{
157 +       kfree(drv_data);
158 +       return 0;
159 +}
160 +
161 +static const struct of_device_id fab_scaling_ipq806x_match_table[] = {
162 +       { .compatible = "qcom,fab-scaling" },
163 +       { }
164 +};
165 +
166 +static struct platform_driver fab_scaling_ipq806x_driver = {
167 +       .probe          = ipq806x_fab_scaling_probe,
168 +       .remove         = ipq806x_fab_scaling_remove,
169 +       .driver         = {
170 +               .name   = "fab-scaling",
171 +               .of_match_table = fab_scaling_ipq806x_match_table,
172 +       },
173 +};
174 +
175 +static int __init fab_scaling_ipq806x_init(void)
176 +{
177 +       return platform_driver_register(&fab_scaling_ipq806x_driver);
178 +}
179 +late_initcall(fab_scaling_ipq806x_init);
180 +
181 +static void __exit fab_scaling_ipq806x_exit(void)
182 +{
183 +       platform_driver_unregister(&fab_scaling_ipq806x_driver);
184 +}
185 +module_exit(fab_scaling_ipq806x_exit);
186 --- /dev/null
187 +++ b/include/linux/fab_scaling.h
188 @@ -0,0 +1,31 @@
189 +/*
190 + * Copyright (c) 2015, The Linux Foundation. All rights reserved.
191 + *
192 + * Permission to use, copy, modify, and/or distribute this software for any
193 + * purpose with or without fee is hereby granted, provided that the above
194 + * copyright notice and this permission notice appear in all copies.
195 + *
196 + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
197 + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
198 + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
199 + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
200 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
201 + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
202 + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
203 + */
204 +
205 +
206 +#ifndef __FAB_SCALING_H
207 +#define __FAB_SCALING_H
208 +
209 +/**
210 + * scale_fabrics - Scale DDR and APPS FABRICS
211 + *
212 + * This function monitors all the registered clocks and does APPS
213 + * and DDR FABRIC scaling based on the idle frequencies with which
214 + * it was registered.
215 + *
216 + */
217 +int scale_fabrics(unsigned long max_cpu_freq);
218 +
219 +#endif
220 --- a/drivers/cpufreq/qcom-cpufreq-krait.c
221 +++ b/drivers/cpufreq/qcom-cpufreq-krait.c
222 @@ -15,6 +15,7 @@
223  #include <linux/regulator/consumer.h>
224  #include <linux/slab.h>
225  #include <linux/thermal.h>
226 +#include <linux/fab_scaling.h>
227  
228  #include "cpufreq-dt.h"
229  
230 @@ -74,6 +75,13 @@ static int set_target(struct cpufreq_pol
231                         goto l2_scale_fail;
232                 }
233  
234 +               /*
235 +                * Scale fabrics with max freq across all cores
236 +                */
237 +               ret = scale_fabrics(target_freq);
238 +               if (ret)
239 +                       goto l2_scale_fail;
240 +
241                 opp = dev_pm_opp_find_level_exact(l2_dev, level);
242                 if (IS_ERR(opp)) {
243                         dev_err(l2_dev,