aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/cpufreq/arm_big_little.c2
-rw-r--r--drivers/cpufreq/cpufreq-dt.c2
-rw-r--r--drivers/cpufreq/imx6q-cpufreq.c1
-rw-r--r--drivers/cpufreq/mediatek-cpufreq.c2
-rw-r--r--drivers/cpufreq/omap-cpufreq.c4
-rw-r--r--drivers/cpufreq/scmi-cpufreq.c39
-rw-r--r--drivers/cpufreq/scpi-cpufreq.c3
-rw-r--r--drivers/opp/core.c11
-rw-r--r--drivers/opp/debugfs.c110
-rw-r--r--drivers/opp/opp.h15
10 files changed, 87 insertions, 102 deletions
diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c
index cf62a1f64dd7..7fe52fcddcf1 100644
--- a/drivers/cpufreq/arm_big_little.c
+++ b/drivers/cpufreq/arm_big_little.c
@@ -487,6 +487,8 @@ static int bL_cpufreq_init(struct cpufreq_policy *policy)
487 policy->cpuinfo.transition_latency = 487 policy->cpuinfo.transition_latency =
488 arm_bL_ops->get_transition_latency(cpu_dev); 488 arm_bL_ops->get_transition_latency(cpu_dev);
489 489
490 dev_pm_opp_of_register_em(policy->cpus);
491
490 if (is_bL_switching_enabled()) 492 if (is_bL_switching_enabled())
491 per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu); 493 per_cpu(cpu_last_req_freq, policy->cpu) = clk_get_cpu_rate(policy->cpu);
492 494
diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c
index 1aefaa1b0ca2..bde28878725b 100644
--- a/drivers/cpufreq/cpufreq-dt.c
+++ b/drivers/cpufreq/cpufreq-dt.c
@@ -278,6 +278,8 @@ static int cpufreq_init(struct cpufreq_policy *policy)
278 policy->cpuinfo.transition_latency = transition_latency; 278 policy->cpuinfo.transition_latency = transition_latency;
279 policy->dvfs_possible_from_any_cpu = true; 279 policy->dvfs_possible_from_any_cpu = true;
280 280
281 dev_pm_opp_of_register_em(policy->cpus);
282
281 return 0; 283 return 0;
282 284
283out_free_cpufreq_table: 285out_free_cpufreq_table:
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index ca955713e070..a4ff09f91c8f 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -198,6 +198,7 @@ static int imx6q_cpufreq_init(struct cpufreq_policy *policy)
198 policy->clk = clks[ARM].clk; 198 policy->clk = clks[ARM].clk;
199 ret = cpufreq_generic_init(policy, freq_table, transition_latency); 199 ret = cpufreq_generic_init(policy, freq_table, transition_latency);
200 policy->suspend_freq = max_freq; 200 policy->suspend_freq = max_freq;
201 dev_pm_opp_of_register_em(policy->cpus);
201 202
202 return ret; 203 return ret;
203} 204}
diff --git a/drivers/cpufreq/mediatek-cpufreq.c b/drivers/cpufreq/mediatek-cpufreq.c
index 4229fcc31310..48e9829274c6 100644
--- a/drivers/cpufreq/mediatek-cpufreq.c
+++ b/drivers/cpufreq/mediatek-cpufreq.c
@@ -456,6 +456,8 @@ static int mtk_cpufreq_init(struct cpufreq_policy *policy)
456 policy->driver_data = info; 456 policy->driver_data = info;
457 policy->clk = info->cpu_clk; 457 policy->clk = info->cpu_clk;
458 458
459 dev_pm_opp_of_register_em(policy->cpus);
460
459 return 0; 461 return 0;
460} 462}
461 463
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 71e81bbf031b..68052b74d28f 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -133,8 +133,10 @@ static int omap_cpu_init(struct cpufreq_policy *policy)
133 133
134 /* FIXME: what's the actual transition time? */ 134 /* FIXME: what's the actual transition time? */
135 result = cpufreq_generic_init(policy, freq_table, 300 * 1000); 135 result = cpufreq_generic_init(policy, freq_table, 300 * 1000);
136 if (!result) 136 if (!result) {
137 dev_pm_opp_of_register_em(policy->cpus);
137 return 0; 138 return 0;
139 }
138 140
139 freq_table_free(); 141 freq_table_free();
140fail: 142fail:
diff --git a/drivers/cpufreq/scmi-cpufreq.c b/drivers/cpufreq/scmi-cpufreq.c
index c47182fc64ea..e6182c89df79 100644
--- a/drivers/cpufreq/scmi-cpufreq.c
+++ b/drivers/cpufreq/scmi-cpufreq.c
@@ -11,6 +11,7 @@
11#include <linux/cpu.h> 11#include <linux/cpu.h>
12#include <linux/cpufreq.h> 12#include <linux/cpufreq.h>
13#include <linux/cpumask.h> 13#include <linux/cpumask.h>
14#include <linux/energy_model.h>
14#include <linux/export.h> 15#include <linux/export.h>
15#include <linux/module.h> 16#include <linux/module.h>
16#include <linux/pm_opp.h> 17#include <linux/pm_opp.h>
@@ -101,13 +102,42 @@ scmi_get_sharing_cpus(struct device *cpu_dev, struct cpumask *cpumask)
101 return 0; 102 return 0;
102} 103}
103 104
105static int __maybe_unused
106scmi_get_cpu_power(unsigned long *power, unsigned long *KHz, int cpu)
107{
108 struct device *cpu_dev = get_cpu_device(cpu);
109 unsigned long Hz;
110 int ret, domain;
111
112 if (!cpu_dev) {
113 pr_err("failed to get cpu%d device\n", cpu);
114 return -ENODEV;
115 }
116
117 domain = handle->perf_ops->device_domain_id(cpu_dev);
118 if (domain < 0)
119 return domain;
120
121 /* Get the power cost of the performance domain. */
122 Hz = *KHz * 1000;
123 ret = handle->perf_ops->est_power_get(handle, domain, &Hz, power);
124 if (ret)
125 return ret;
126
127 /* The EM framework specifies the frequency in KHz. */
128 *KHz = Hz / 1000;
129
130 return 0;
131}
132
104static int scmi_cpufreq_init(struct cpufreq_policy *policy) 133static int scmi_cpufreq_init(struct cpufreq_policy *policy)
105{ 134{
106 int ret; 135 int ret, nr_opp;
107 unsigned int latency; 136 unsigned int latency;
108 struct device *cpu_dev; 137 struct device *cpu_dev;
109 struct scmi_data *priv; 138 struct scmi_data *priv;
110 struct cpufreq_frequency_table *freq_table; 139 struct cpufreq_frequency_table *freq_table;
140 struct em_data_callback em_cb = EM_DATA_CB(scmi_get_cpu_power);
111 141
112 cpu_dev = get_cpu_device(policy->cpu); 142 cpu_dev = get_cpu_device(policy->cpu);
113 if (!cpu_dev) { 143 if (!cpu_dev) {
@@ -134,8 +164,8 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
134 return ret; 164 return ret;
135 } 165 }
136 166
137 ret = dev_pm_opp_get_opp_count(cpu_dev); 167 nr_opp = dev_pm_opp_get_opp_count(cpu_dev);
138 if (ret <= 0) { 168 if (nr_opp <= 0) {
139 dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n"); 169 dev_dbg(cpu_dev, "OPP table is not ready, deferring probe\n");
140 ret = -EPROBE_DEFER; 170 ret = -EPROBE_DEFER;
141 goto out_free_opp; 171 goto out_free_opp;
@@ -169,6 +199,9 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
169 policy->cpuinfo.transition_latency = latency; 199 policy->cpuinfo.transition_latency = latency;
170 200
171 policy->fast_switch_possible = true; 201 policy->fast_switch_possible = true;
202
203 em_register_perf_domain(policy->cpus, nr_opp, &em_cb);
204
172 return 0; 205 return 0;
173 206
174out_free_priv: 207out_free_priv:
diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c
index 1db2f6927e13..3f49427766b8 100644
--- a/drivers/cpufreq/scpi-cpufreq.c
+++ b/drivers/cpufreq/scpi-cpufreq.c
@@ -168,6 +168,9 @@ static int scpi_cpufreq_init(struct cpufreq_policy *policy)
168 policy->cpuinfo.transition_latency = latency; 168 policy->cpuinfo.transition_latency = latency;
169 169
170 policy->fast_switch_possible = false; 170 policy->fast_switch_possible = false;
171
172 dev_pm_opp_of_register_em(policy->cpus);
173
171 return 0; 174 return 0;
172 175
173out_free_cpufreq_table: 176out_free_cpufreq_table:
diff --git a/drivers/opp/core.c b/drivers/opp/core.c
index 4e00301060cf..410892d54bc4 100644
--- a/drivers/opp/core.c
+++ b/drivers/opp/core.c
@@ -792,7 +792,6 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
792 struct opp_table *opp_table) 792 struct opp_table *opp_table)
793{ 793{
794 struct opp_device *opp_dev; 794 struct opp_device *opp_dev;
795 int ret;
796 795
797 opp_dev = kzalloc(sizeof(*opp_dev), GFP_KERNEL); 796 opp_dev = kzalloc(sizeof(*opp_dev), GFP_KERNEL);
798 if (!opp_dev) 797 if (!opp_dev)
@@ -804,10 +803,7 @@ static struct opp_device *_add_opp_dev_unlocked(const struct device *dev,
804 list_add(&opp_dev->node, &opp_table->dev_list); 803 list_add(&opp_dev->node, &opp_table->dev_list);
805 804
806 /* Create debugfs entries for the opp_table */ 805 /* Create debugfs entries for the opp_table */
807 ret = opp_debug_register(opp_dev, opp_table); 806 opp_debug_register(opp_dev, opp_table);
808 if (ret)
809 dev_err(dev, "%s: Failed to register opp debugfs (%d)\n",
810 __func__, ret);
811 807
812 return opp_dev; 808 return opp_dev;
813} 809}
@@ -1228,10 +1224,7 @@ int _opp_add(struct device *dev, struct dev_pm_opp *new_opp,
1228 new_opp->opp_table = opp_table; 1224 new_opp->opp_table = opp_table;
1229 kref_init(&new_opp->kref); 1225 kref_init(&new_opp->kref);
1230 1226
1231 ret = opp_debug_create_one(new_opp, opp_table); 1227 opp_debug_create_one(new_opp, opp_table);
1232 if (ret)
1233 dev_err(dev, "%s: Failed to register opp to debugfs (%d)\n",
1234 __func__, ret);
1235 1228
1236 if (!_opp_supported_by_regulators(new_opp, opp_table)) { 1229 if (!_opp_supported_by_regulators(new_opp, opp_table)) {
1237 new_opp->available = false; 1230 new_opp->available = false;
diff --git a/drivers/opp/debugfs.c b/drivers/opp/debugfs.c
index e6828e5f81b0..a1c57fe14de4 100644
--- a/drivers/opp/debugfs.c
+++ b/drivers/opp/debugfs.c
@@ -35,7 +35,7 @@ void opp_debug_remove_one(struct dev_pm_opp *opp)
35 debugfs_remove_recursive(opp->dentry); 35 debugfs_remove_recursive(opp->dentry);
36} 36}
37 37
38static bool opp_debug_create_supplies(struct dev_pm_opp *opp, 38static void opp_debug_create_supplies(struct dev_pm_opp *opp,
39 struct opp_table *opp_table, 39 struct opp_table *opp_table,
40 struct dentry *pdentry) 40 struct dentry *pdentry)
41{ 41{
@@ -50,30 +50,21 @@ static bool opp_debug_create_supplies(struct dev_pm_opp *opp,
50 /* Create per-opp directory */ 50 /* Create per-opp directory */
51 d = debugfs_create_dir(name, pdentry); 51 d = debugfs_create_dir(name, pdentry);
52 52
53 if (!d) 53 debugfs_create_ulong("u_volt_target", S_IRUGO, d,
54 return false; 54 &opp->supplies[i].u_volt);
55 55
56 if (!debugfs_create_ulong("u_volt_target", S_IRUGO, d, 56 debugfs_create_ulong("u_volt_min", S_IRUGO, d,
57 &opp->supplies[i].u_volt)) 57 &opp->supplies[i].u_volt_min);
58 return false;
59 58
60 if (!debugfs_create_ulong("u_volt_min", S_IRUGO, d, 59 debugfs_create_ulong("u_volt_max", S_IRUGO, d,
61 &opp->supplies[i].u_volt_min)) 60 &opp->supplies[i].u_volt_max);
62 return false;
63 61
64 if (!debugfs_create_ulong("u_volt_max", S_IRUGO, d, 62 debugfs_create_ulong("u_amp", S_IRUGO, d,
65 &opp->supplies[i].u_volt_max)) 63 &opp->supplies[i].u_amp);
66 return false;
67
68 if (!debugfs_create_ulong("u_amp", S_IRUGO, d,
69 &opp->supplies[i].u_amp))
70 return false;
71 } 64 }
72
73 return true;
74} 65}
75 66
76int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table) 67void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
77{ 68{
78 struct dentry *pdentry = opp_table->dentry; 69 struct dentry *pdentry = opp_table->dentry;
79 struct dentry *d; 70 struct dentry *d;
@@ -95,40 +86,23 @@ int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table)
95 86
96 /* Create per-opp directory */ 87 /* Create per-opp directory */
97 d = debugfs_create_dir(name, pdentry); 88 d = debugfs_create_dir(name, pdentry);
98 if (!d)
99 return -ENOMEM;
100
101 if (!debugfs_create_bool("available", S_IRUGO, d, &opp->available))
102 return -ENOMEM;
103
104 if (!debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic))
105 return -ENOMEM;
106
107 if (!debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo))
108 return -ENOMEM;
109
110 if (!debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend))
111 return -ENOMEM;
112
113 if (!debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate))
114 return -ENOMEM;
115 89
116 if (!debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate)) 90 debugfs_create_bool("available", S_IRUGO, d, &opp->available);
117 return -ENOMEM; 91 debugfs_create_bool("dynamic", S_IRUGO, d, &opp->dynamic);
92 debugfs_create_bool("turbo", S_IRUGO, d, &opp->turbo);
93 debugfs_create_bool("suspend", S_IRUGO, d, &opp->suspend);
94 debugfs_create_u32("performance_state", S_IRUGO, d, &opp->pstate);
95 debugfs_create_ulong("rate_hz", S_IRUGO, d, &opp->rate);
96 debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
97 &opp->clock_latency_ns);
118 98
119 if (!opp_debug_create_supplies(opp, opp_table, d)) 99 opp_debug_create_supplies(opp, opp_table, d);
120 return -ENOMEM;
121
122 if (!debugfs_create_ulong("clock_latency_ns", S_IRUGO, d,
123 &opp->clock_latency_ns))
124 return -ENOMEM;
125 100
126 opp->dentry = d; 101 opp->dentry = d;
127 return 0;
128} 102}
129 103
130static int opp_list_debug_create_dir(struct opp_device *opp_dev, 104static void opp_list_debug_create_dir(struct opp_device *opp_dev,
131 struct opp_table *opp_table) 105 struct opp_table *opp_table)
132{ 106{
133 const struct device *dev = opp_dev->dev; 107 const struct device *dev = opp_dev->dev;
134 struct dentry *d; 108 struct dentry *d;
@@ -137,36 +111,21 @@ static int opp_list_debug_create_dir(struct opp_device *opp_dev,
137 111
138 /* Create device specific directory */ 112 /* Create device specific directory */
139 d = debugfs_create_dir(opp_table->dentry_name, rootdir); 113 d = debugfs_create_dir(opp_table->dentry_name, rootdir);
140 if (!d) {
141 dev_err(dev, "%s: Failed to create debugfs dir\n", __func__);
142 return -ENOMEM;
143 }
144 114
145 opp_dev->dentry = d; 115 opp_dev->dentry = d;
146 opp_table->dentry = d; 116 opp_table->dentry = d;
147
148 return 0;
149} 117}
150 118
151static int opp_list_debug_create_link(struct opp_device *opp_dev, 119static void opp_list_debug_create_link(struct opp_device *opp_dev,
152 struct opp_table *opp_table) 120 struct opp_table *opp_table)
153{ 121{
154 const struct device *dev = opp_dev->dev;
155 char name[NAME_MAX]; 122 char name[NAME_MAX];
156 struct dentry *d;
157 123
158 opp_set_dev_name(opp_dev->dev, name); 124 opp_set_dev_name(opp_dev->dev, name);
159 125
160 /* Create device specific directory link */ 126 /* Create device specific directory link */
161 d = debugfs_create_symlink(name, rootdir, opp_table->dentry_name); 127 opp_dev->dentry = debugfs_create_symlink(name, rootdir,
162 if (!d) { 128 opp_table->dentry_name);
163 dev_err(dev, "%s: Failed to create link\n", __func__);
164 return -ENOMEM;
165 }
166
167 opp_dev->dentry = d;
168
169 return 0;
170} 129}
171 130
172/** 131/**
@@ -177,20 +136,13 @@ static int opp_list_debug_create_link(struct opp_device *opp_dev,
177 * Dynamically adds device specific directory in debugfs 'opp' directory. If the 136 * Dynamically adds device specific directory in debugfs 'opp' directory. If the
178 * device-opp is shared with other devices, then links will be created for all 137 * device-opp is shared with other devices, then links will be created for all
179 * devices except the first. 138 * devices except the first.
180 *
181 * Return: 0 on success, otherwise negative error.
182 */ 139 */
183int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table) 140void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table)
184{ 141{
185 if (!rootdir) {
186 pr_debug("%s: Uninitialized rootdir\n", __func__);
187 return -EINVAL;
188 }
189
190 if (opp_table->dentry) 142 if (opp_table->dentry)
191 return opp_list_debug_create_link(opp_dev, opp_table); 143 opp_list_debug_create_link(opp_dev, opp_table);
192 144 else
193 return opp_list_debug_create_dir(opp_dev, opp_table); 145 opp_list_debug_create_dir(opp_dev, opp_table);
194} 146}
195 147
196static void opp_migrate_dentry(struct opp_device *opp_dev, 148static void opp_migrate_dentry(struct opp_device *opp_dev,
@@ -252,10 +204,6 @@ static int __init opp_debug_init(void)
252{ 204{
253 /* Create /sys/kernel/debug/opp directory */ 205 /* Create /sys/kernel/debug/opp directory */
254 rootdir = debugfs_create_dir("opp", NULL); 206 rootdir = debugfs_create_dir("opp", NULL);
255 if (!rootdir) {
256 pr_err("%s: Failed to create root directory\n", __func__);
257 return -ENOMEM;
258 }
259 207
260 return 0; 208 return 0;
261} 209}
diff --git a/drivers/opp/opp.h b/drivers/opp/opp.h
index e24d81497375..810a85b9a66d 100644
--- a/drivers/opp/opp.h
+++ b/drivers/opp/opp.h
@@ -236,18 +236,17 @@ static inline void _of_opp_free_required_opps(struct opp_table *opp_table,
236 236
237#ifdef CONFIG_DEBUG_FS 237#ifdef CONFIG_DEBUG_FS
238void opp_debug_remove_one(struct dev_pm_opp *opp); 238void opp_debug_remove_one(struct dev_pm_opp *opp);
239int opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table); 239void opp_debug_create_one(struct dev_pm_opp *opp, struct opp_table *opp_table);
240int opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table); 240void opp_debug_register(struct opp_device *opp_dev, struct opp_table *opp_table);
241void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table); 241void opp_debug_unregister(struct opp_device *opp_dev, struct opp_table *opp_table);
242#else 242#else
243static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {} 243static inline void opp_debug_remove_one(struct dev_pm_opp *opp) {}
244 244
245static inline int opp_debug_create_one(struct dev_pm_opp *opp, 245static inline void opp_debug_create_one(struct dev_pm_opp *opp,
246 struct opp_table *opp_table) 246 struct opp_table *opp_table) { }
247{ return 0; } 247
248static inline int opp_debug_register(struct opp_device *opp_dev, 248static inline void opp_debug_register(struct opp_device *opp_dev,
249 struct opp_table *opp_table) 249 struct opp_table *opp_table) { }
250{ return 0; }
251 250
252static inline void opp_debug_unregister(struct opp_device *opp_dev, 251static inline void opp_debug_unregister(struct opp_device *opp_dev,
253 struct opp_table *opp_table) 252 struct opp_table *opp_table)