1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright 2021 Linaro Limited
5 * Author: Daniel Lezcano <daniel.lezcano@linaro.org>
7 * The devfreq device combined with the energy model and the load can
8 * give an estimation of the power consumption as well as limiting the
12 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14 #include <linux/cpumask.h>
15 #include <linux/devfreq.h>
16 #include <linux/dtpm.h>
17 #include <linux/energy_model.h>
19 #include <linux/pm_qos.h>
20 #include <linux/slab.h>
21 #include <linux/units.h>
25 struct dev_pm_qos_request qos_req
;
26 struct devfreq
*devfreq
;
29 static struct dtpm_devfreq
*to_dtpm_devfreq(struct dtpm
*dtpm
)
31 return container_of(dtpm
, struct dtpm_devfreq
, dtpm
);
34 static int update_pd_power_uw(struct dtpm
*dtpm
)
36 struct dtpm_devfreq
*dtpm_devfreq
= to_dtpm_devfreq(dtpm
);
37 struct devfreq
*devfreq
= dtpm_devfreq
->devfreq
;
38 struct device
*dev
= devfreq
->dev
.parent
;
39 struct em_perf_domain
*pd
= em_pd_get(dev
);
41 dtpm
->power_min
= pd
->table
[0].power
;
42 dtpm
->power_min
*= MICROWATT_PER_MILLIWATT
;
44 dtpm
->power_max
= pd
->table
[pd
->nr_perf_states
- 1].power
;
45 dtpm
->power_max
*= MICROWATT_PER_MILLIWATT
;
50 static u64
set_pd_power_limit(struct dtpm
*dtpm
, u64 power_limit
)
52 struct dtpm_devfreq
*dtpm_devfreq
= to_dtpm_devfreq(dtpm
);
53 struct devfreq
*devfreq
= dtpm_devfreq
->devfreq
;
54 struct device
*dev
= devfreq
->dev
.parent
;
55 struct em_perf_domain
*pd
= em_pd_get(dev
);
60 for (i
= 0; i
< pd
->nr_perf_states
; i
++) {
62 power
= pd
->table
[i
].power
* MICROWATT_PER_MILLIWATT
;
63 if (power
> power_limit
)
67 freq
= pd
->table
[i
- 1].frequency
;
69 dev_pm_qos_update_request(&dtpm_devfreq
->qos_req
, freq
);
71 power_limit
= pd
->table
[i
- 1].power
* MICROWATT_PER_MILLIWATT
;
76 static void _normalize_load(struct devfreq_dev_status
*status
)
78 if (status
->total_time
> 0xfffff) {
79 status
->total_time
>>= 10;
80 status
->busy_time
>>= 10;
83 status
->busy_time
<<= 10;
84 status
->busy_time
/= status
->total_time
? : 1;
86 status
->busy_time
= status
->busy_time
? : 1;
87 status
->total_time
= 1024;
90 static u64
get_pd_power_uw(struct dtpm
*dtpm
)
92 struct dtpm_devfreq
*dtpm_devfreq
= to_dtpm_devfreq(dtpm
);
93 struct devfreq
*devfreq
= dtpm_devfreq
->devfreq
;
94 struct device
*dev
= devfreq
->dev
.parent
;
95 struct em_perf_domain
*pd
= em_pd_get(dev
);
96 struct devfreq_dev_status status
;
101 mutex_lock(&devfreq
->lock
);
102 status
= devfreq
->last_status
;
103 mutex_unlock(&devfreq
->lock
);
105 freq
= DIV_ROUND_UP(status
.current_frequency
, HZ_PER_KHZ
);
106 _normalize_load(&status
);
108 for (i
= 0; i
< pd
->nr_perf_states
; i
++) {
110 if (pd
->table
[i
].frequency
< freq
)
113 power
= pd
->table
[i
].power
* MICROWATT_PER_MILLIWATT
;
114 power
*= status
.busy_time
;
123 static void pd_release(struct dtpm
*dtpm
)
125 struct dtpm_devfreq
*dtpm_devfreq
= to_dtpm_devfreq(dtpm
);
127 if (dev_pm_qos_request_active(&dtpm_devfreq
->qos_req
))
128 dev_pm_qos_remove_request(&dtpm_devfreq
->qos_req
);
133 static struct dtpm_ops dtpm_ops
= {
134 .set_power_uw
= set_pd_power_limit
,
135 .get_power_uw
= get_pd_power_uw
,
136 .update_power_uw
= update_pd_power_uw
,
137 .release
= pd_release
,
140 static int __dtpm_devfreq_setup(struct devfreq
*devfreq
, struct dtpm
*parent
)
142 struct device
*dev
= devfreq
->dev
.parent
;
143 struct dtpm_devfreq
*dtpm_devfreq
;
144 struct em_perf_domain
*pd
;
149 ret
= dev_pm_opp_of_register_em(dev
, NULL
);
151 pr_err("No energy model available for '%s'\n", dev_name(dev
));
156 dtpm_devfreq
= kzalloc(sizeof(*dtpm_devfreq
), GFP_KERNEL
);
160 dtpm_init(&dtpm_devfreq
->dtpm
, &dtpm_ops
);
162 dtpm_devfreq
->devfreq
= devfreq
;
164 ret
= dtpm_register(dev_name(dev
), &dtpm_devfreq
->dtpm
, parent
);
166 pr_err("Failed to register '%s': %d\n", dev_name(dev
), ret
);
171 ret
= dev_pm_qos_add_request(dev
, &dtpm_devfreq
->qos_req
,
172 DEV_PM_QOS_MAX_FREQUENCY
,
173 PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE
);
175 pr_err("Failed to add QoS request: %d\n", ret
);
176 goto out_dtpm_unregister
;
179 dtpm_update_power(&dtpm_devfreq
->dtpm
);
184 dtpm_unregister(&dtpm_devfreq
->dtpm
);
189 static int dtpm_devfreq_setup(struct dtpm
*dtpm
, struct device_node
*np
)
191 struct devfreq
*devfreq
;
193 devfreq
= devfreq_get_devfreq_by_node(np
);
197 return __dtpm_devfreq_setup(devfreq
, dtpm
);
200 struct dtpm_subsys_ops dtpm_devfreq_ops
= {
201 .name
= KBUILD_MODNAME
,
202 .setup
= dtpm_devfreq_setup
,