1 // SPDX-License-Identifier: GPL-2.0
3 * System Control and Management Interface (SCMI) Performance Protocol
5 * Copyright (C) 2018 ARM Ltd.
8 #define pr_fmt(fmt) "SCMI Notifications PERF - " fmt
10 #include <linux/bits.h>
13 #include <linux/io-64-nonatomic-hi-lo.h>
14 #include <linux/platform_device.h>
15 #include <linux/pm_opp.h>
16 #include <linux/scmi_protocol.h>
17 #include <linux/sort.h>
22 enum scmi_performance_protocol_cmd
{
23 PERF_DOMAIN_ATTRIBUTES
= 0x3,
24 PERF_DESCRIBE_LEVELS
= 0x4,
25 PERF_LIMITS_SET
= 0x5,
26 PERF_LIMITS_GET
= 0x6,
29 PERF_NOTIFY_LIMITS
= 0x9,
30 PERF_NOTIFY_LEVEL
= 0xa,
31 PERF_DESCRIBE_FASTCHANNEL
= 0xb,
40 struct scmi_msg_resp_perf_attributes
{
43 #define POWER_SCALE_IN_MILLIWATT(x) ((x) & BIT(0))
44 __le32 stats_addr_low
;
45 __le32 stats_addr_high
;
49 struct scmi_msg_resp_perf_domain_attributes
{
51 #define SUPPORTS_SET_LIMITS(x) ((x) & BIT(31))
52 #define SUPPORTS_SET_PERF_LVL(x) ((x) & BIT(30))
53 #define SUPPORTS_PERF_LIMIT_NOTIFY(x) ((x) & BIT(29))
54 #define SUPPORTS_PERF_LEVEL_NOTIFY(x) ((x) & BIT(28))
55 #define SUPPORTS_PERF_FASTCHANNELS(x) ((x) & BIT(27))
57 __le32 sustained_freq_khz
;
58 __le32 sustained_perf_level
;
59 u8 name
[SCMI_MAX_STR_SIZE
];
62 struct scmi_msg_perf_describe_levels
{
67 struct scmi_perf_set_limits
{
73 struct scmi_perf_get_limits
{
78 struct scmi_perf_set_level
{
83 struct scmi_perf_notify_level_or_limits
{
88 struct scmi_perf_limits_notify_payld
{
95 struct scmi_perf_level_notify_payld
{
98 __le32 performance_level
;
101 struct scmi_msg_resp_perf_describe_levels
{
103 __le16 num_remaining
;
107 __le16 transition_latency_us
;
112 struct scmi_perf_get_fc_info
{
117 struct scmi_msg_resp_perf_desc_fc
{
119 #define SUPPORTS_DOORBELL(x) ((x) & BIT(0))
120 #define DOORBELL_REG_WIDTH(x) FIELD_GET(GENMASK(2, 1), (x))
122 __le32 chan_addr_low
;
123 __le32 chan_addr_high
;
129 __le32 db_preserve_lmask
;
130 __le32 db_preserve_hmask
;
133 struct scmi_fc_db_info
{
140 struct scmi_fc_info
{
141 void __iomem
*level_set_addr
;
142 void __iomem
*limit_set_addr
;
143 void __iomem
*level_get_addr
;
144 void __iomem
*limit_get_addr
;
145 struct scmi_fc_db_info
*level_set_db
;
146 struct scmi_fc_db_info
*limit_set_db
;
149 struct perf_dom_info
{
152 bool perf_limit_notify
;
153 bool perf_level_notify
;
154 bool perf_fastchannels
;
156 u32 sustained_freq_khz
;
157 u32 sustained_perf_level
;
159 char name
[SCMI_MAX_STR_SIZE
];
160 struct scmi_opp opp
[MAX_OPPS
];
161 struct scmi_fc_info
*fc_info
;
164 struct scmi_perf_info
{
170 struct perf_dom_info
*dom_info
;
173 static enum scmi_performance_protocol_cmd evt_2_cmd
[] = {
178 static int scmi_perf_attributes_get(const struct scmi_handle
*handle
,
179 struct scmi_perf_info
*pi
)
183 struct scmi_msg_resp_perf_attributes
*attr
;
185 ret
= scmi_xfer_get_init(handle
, PROTOCOL_ATTRIBUTES
,
186 SCMI_PROTOCOL_PERF
, 0, sizeof(*attr
), &t
);
192 ret
= scmi_do_xfer(handle
, t
);
194 u16 flags
= le16_to_cpu(attr
->flags
);
196 pi
->num_domains
= le16_to_cpu(attr
->num_domains
);
197 pi
->power_scale_mw
= POWER_SCALE_IN_MILLIWATT(flags
);
198 pi
->stats_addr
= le32_to_cpu(attr
->stats_addr_low
) |
199 (u64
)le32_to_cpu(attr
->stats_addr_high
) << 32;
200 pi
->stats_size
= le32_to_cpu(attr
->stats_size
);
203 scmi_xfer_put(handle
, t
);
208 scmi_perf_domain_attributes_get(const struct scmi_handle
*handle
, u32 domain
,
209 struct perf_dom_info
*dom_info
)
213 struct scmi_msg_resp_perf_domain_attributes
*attr
;
215 ret
= scmi_xfer_get_init(handle
, PERF_DOMAIN_ATTRIBUTES
,
216 SCMI_PROTOCOL_PERF
, sizeof(domain
),
221 put_unaligned_le32(domain
, t
->tx
.buf
);
224 ret
= scmi_do_xfer(handle
, t
);
226 u32 flags
= le32_to_cpu(attr
->flags
);
228 dom_info
->set_limits
= SUPPORTS_SET_LIMITS(flags
);
229 dom_info
->set_perf
= SUPPORTS_SET_PERF_LVL(flags
);
230 dom_info
->perf_limit_notify
= SUPPORTS_PERF_LIMIT_NOTIFY(flags
);
231 dom_info
->perf_level_notify
= SUPPORTS_PERF_LEVEL_NOTIFY(flags
);
232 dom_info
->perf_fastchannels
= SUPPORTS_PERF_FASTCHANNELS(flags
);
233 dom_info
->sustained_freq_khz
=
234 le32_to_cpu(attr
->sustained_freq_khz
);
235 dom_info
->sustained_perf_level
=
236 le32_to_cpu(attr
->sustained_perf_level
);
237 if (!dom_info
->sustained_freq_khz
||
238 !dom_info
->sustained_perf_level
)
239 /* CPUFreq converts to kHz, hence default 1000 */
240 dom_info
->mult_factor
= 1000;
242 dom_info
->mult_factor
=
243 (dom_info
->sustained_freq_khz
* 1000) /
244 dom_info
->sustained_perf_level
;
245 strlcpy(dom_info
->name
, attr
->name
, SCMI_MAX_STR_SIZE
);
248 scmi_xfer_put(handle
, t
);
252 static int opp_cmp_func(const void *opp1
, const void *opp2
)
254 const struct scmi_opp
*t1
= opp1
, *t2
= opp2
;
256 return t1
->perf
- t2
->perf
;
260 scmi_perf_describe_levels_get(const struct scmi_handle
*handle
, u32 domain
,
261 struct perf_dom_info
*perf_dom
)
265 u16 num_returned
, num_remaining
;
267 struct scmi_opp
*opp
;
268 struct scmi_msg_perf_describe_levels
*dom_info
;
269 struct scmi_msg_resp_perf_describe_levels
*level_info
;
271 ret
= scmi_xfer_get_init(handle
, PERF_DESCRIBE_LEVELS
,
272 SCMI_PROTOCOL_PERF
, sizeof(*dom_info
), 0, &t
);
276 dom_info
= t
->tx
.buf
;
277 level_info
= t
->rx
.buf
;
280 dom_info
->domain
= cpu_to_le32(domain
);
281 /* Set the number of OPPs to be skipped/already read */
282 dom_info
->level_index
= cpu_to_le32(tot_opp_cnt
);
284 ret
= scmi_do_xfer(handle
, t
);
288 num_returned
= le16_to_cpu(level_info
->num_returned
);
289 num_remaining
= le16_to_cpu(level_info
->num_remaining
);
290 if (tot_opp_cnt
+ num_returned
> MAX_OPPS
) {
291 dev_err(handle
->dev
, "No. of OPPs exceeded MAX_OPPS");
295 opp
= &perf_dom
->opp
[tot_opp_cnt
];
296 for (cnt
= 0; cnt
< num_returned
; cnt
++, opp
++) {
297 opp
->perf
= le32_to_cpu(level_info
->opp
[cnt
].perf_val
);
298 opp
->power
= le32_to_cpu(level_info
->opp
[cnt
].power
);
299 opp
->trans_latency_us
= le16_to_cpu
300 (level_info
->opp
[cnt
].transition_latency_us
);
302 dev_dbg(handle
->dev
, "Level %d Power %d Latency %dus\n",
303 opp
->perf
, opp
->power
, opp
->trans_latency_us
);
306 tot_opp_cnt
+= num_returned
;
308 scmi_reset_rx_to_maxsz(handle
, t
);
310 * check for both returned and remaining to avoid infinite
311 * loop due to buggy firmware
313 } while (num_returned
&& num_remaining
);
315 perf_dom
->opp_count
= tot_opp_cnt
;
316 scmi_xfer_put(handle
, t
);
318 sort(perf_dom
->opp
, tot_opp_cnt
, sizeof(*opp
), opp_cmp_func
, NULL
);
322 #define SCMI_PERF_FC_RING_DB(w) \
327 val = ioread##w(db->addr) & db->mask; \
328 iowrite##w((u##w)db->set | val, db->addr); \
331 static void scmi_perf_fc_ring_db(struct scmi_fc_db_info
*db
)
333 if (!db
|| !db
->addr
)
337 SCMI_PERF_FC_RING_DB(8);
338 else if (db
->width
== 2)
339 SCMI_PERF_FC_RING_DB(16);
340 else if (db
->width
== 4)
341 SCMI_PERF_FC_RING_DB(32);
342 else /* db->width == 8 */
344 SCMI_PERF_FC_RING_DB(64);
350 val
= ioread64_hi_lo(db
->addr
) & db
->mask
;
351 iowrite64_hi_lo(db
->set
| val
, db
->addr
);
356 static int scmi_perf_mb_limits_set(const struct scmi_handle
*handle
, u32 domain
,
357 u32 max_perf
, u32 min_perf
)
361 struct scmi_perf_set_limits
*limits
;
363 ret
= scmi_xfer_get_init(handle
, PERF_LIMITS_SET
, SCMI_PROTOCOL_PERF
,
364 sizeof(*limits
), 0, &t
);
369 limits
->domain
= cpu_to_le32(domain
);
370 limits
->max_level
= cpu_to_le32(max_perf
);
371 limits
->min_level
= cpu_to_le32(min_perf
);
373 ret
= scmi_do_xfer(handle
, t
);
375 scmi_xfer_put(handle
, t
);
379 static int scmi_perf_limits_set(const struct scmi_handle
*handle
, u32 domain
,
380 u32 max_perf
, u32 min_perf
)
382 struct scmi_perf_info
*pi
= handle
->perf_priv
;
383 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
385 if (dom
->fc_info
&& dom
->fc_info
->limit_set_addr
) {
386 iowrite32(max_perf
, dom
->fc_info
->limit_set_addr
);
387 iowrite32(min_perf
, dom
->fc_info
->limit_set_addr
+ 4);
388 scmi_perf_fc_ring_db(dom
->fc_info
->limit_set_db
);
392 return scmi_perf_mb_limits_set(handle
, domain
, max_perf
, min_perf
);
395 static int scmi_perf_mb_limits_get(const struct scmi_handle
*handle
, u32 domain
,
396 u32
*max_perf
, u32
*min_perf
)
400 struct scmi_perf_get_limits
*limits
;
402 ret
= scmi_xfer_get_init(handle
, PERF_LIMITS_GET
, SCMI_PROTOCOL_PERF
,
403 sizeof(__le32
), 0, &t
);
407 put_unaligned_le32(domain
, t
->tx
.buf
);
409 ret
= scmi_do_xfer(handle
, t
);
413 *max_perf
= le32_to_cpu(limits
->max_level
);
414 *min_perf
= le32_to_cpu(limits
->min_level
);
417 scmi_xfer_put(handle
, t
);
421 static int scmi_perf_limits_get(const struct scmi_handle
*handle
, u32 domain
,
422 u32
*max_perf
, u32
*min_perf
)
424 struct scmi_perf_info
*pi
= handle
->perf_priv
;
425 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
427 if (dom
->fc_info
&& dom
->fc_info
->limit_get_addr
) {
428 *max_perf
= ioread32(dom
->fc_info
->limit_get_addr
);
429 *min_perf
= ioread32(dom
->fc_info
->limit_get_addr
+ 4);
433 return scmi_perf_mb_limits_get(handle
, domain
, max_perf
, min_perf
);
436 static int scmi_perf_mb_level_set(const struct scmi_handle
*handle
, u32 domain
,
437 u32 level
, bool poll
)
441 struct scmi_perf_set_level
*lvl
;
443 ret
= scmi_xfer_get_init(handle
, PERF_LEVEL_SET
, SCMI_PROTOCOL_PERF
,
444 sizeof(*lvl
), 0, &t
);
448 t
->hdr
.poll_completion
= poll
;
450 lvl
->domain
= cpu_to_le32(domain
);
451 lvl
->level
= cpu_to_le32(level
);
453 ret
= scmi_do_xfer(handle
, t
);
455 scmi_xfer_put(handle
, t
);
459 static int scmi_perf_level_set(const struct scmi_handle
*handle
, u32 domain
,
460 u32 level
, bool poll
)
462 struct scmi_perf_info
*pi
= handle
->perf_priv
;
463 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
465 if (dom
->fc_info
&& dom
->fc_info
->level_set_addr
) {
466 iowrite32(level
, dom
->fc_info
->level_set_addr
);
467 scmi_perf_fc_ring_db(dom
->fc_info
->level_set_db
);
471 return scmi_perf_mb_level_set(handle
, domain
, level
, poll
);
474 static int scmi_perf_mb_level_get(const struct scmi_handle
*handle
, u32 domain
,
475 u32
*level
, bool poll
)
480 ret
= scmi_xfer_get_init(handle
, PERF_LEVEL_GET
, SCMI_PROTOCOL_PERF
,
481 sizeof(u32
), sizeof(u32
), &t
);
485 t
->hdr
.poll_completion
= poll
;
486 put_unaligned_le32(domain
, t
->tx
.buf
);
488 ret
= scmi_do_xfer(handle
, t
);
490 *level
= get_unaligned_le32(t
->rx
.buf
);
492 scmi_xfer_put(handle
, t
);
496 static int scmi_perf_level_get(const struct scmi_handle
*handle
, u32 domain
,
497 u32
*level
, bool poll
)
499 struct scmi_perf_info
*pi
= handle
->perf_priv
;
500 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
502 if (dom
->fc_info
&& dom
->fc_info
->level_get_addr
) {
503 *level
= ioread32(dom
->fc_info
->level_get_addr
);
507 return scmi_perf_mb_level_get(handle
, domain
, level
, poll
);
510 static int scmi_perf_level_limits_notify(const struct scmi_handle
*handle
,
511 u32 domain
, int message_id
,
516 struct scmi_perf_notify_level_or_limits
*notify
;
518 ret
= scmi_xfer_get_init(handle
, message_id
, SCMI_PROTOCOL_PERF
,
519 sizeof(*notify
), 0, &t
);
524 notify
->domain
= cpu_to_le32(domain
);
525 notify
->notify_enable
= enable
? cpu_to_le32(BIT(0)) : 0;
527 ret
= scmi_do_xfer(handle
, t
);
529 scmi_xfer_put(handle
, t
);
533 static bool scmi_perf_fc_size_is_valid(u32 msg
, u32 size
)
535 if ((msg
== PERF_LEVEL_GET
|| msg
== PERF_LEVEL_SET
) && size
== 4)
537 if ((msg
== PERF_LIMITS_GET
|| msg
== PERF_LIMITS_SET
) && size
== 8)
543 scmi_perf_domain_desc_fc(const struct scmi_handle
*handle
, u32 domain
,
544 u32 message_id
, void __iomem
**p_addr
,
545 struct scmi_fc_db_info
**p_db
)
553 struct scmi_fc_db_info
*db
;
554 struct scmi_perf_get_fc_info
*info
;
555 struct scmi_msg_resp_perf_desc_fc
*resp
;
560 ret
= scmi_xfer_get_init(handle
, PERF_DESCRIBE_FASTCHANNEL
,
562 sizeof(*info
), sizeof(*resp
), &t
);
567 info
->domain
= cpu_to_le32(domain
);
568 info
->message_id
= cpu_to_le32(message_id
);
570 ret
= scmi_do_xfer(handle
, t
);
575 flags
= le32_to_cpu(resp
->attr
);
576 size
= le32_to_cpu(resp
->chan_size
);
577 if (!scmi_perf_fc_size_is_valid(message_id
, size
))
580 phys_addr
= le32_to_cpu(resp
->chan_addr_low
);
581 phys_addr
|= (u64
)le32_to_cpu(resp
->chan_addr_high
) << 32;
582 addr
= devm_ioremap(handle
->dev
, phys_addr
, size
);
587 if (p_db
&& SUPPORTS_DOORBELL(flags
)) {
588 db
= devm_kzalloc(handle
->dev
, sizeof(*db
), GFP_KERNEL
);
592 size
= 1 << DOORBELL_REG_WIDTH(flags
);
593 phys_addr
= le32_to_cpu(resp
->db_addr_low
);
594 phys_addr
|= (u64
)le32_to_cpu(resp
->db_addr_high
) << 32;
595 addr
= devm_ioremap(handle
->dev
, phys_addr
, size
);
601 db
->set
= le32_to_cpu(resp
->db_set_lmask
);
602 db
->set
|= (u64
)le32_to_cpu(resp
->db_set_hmask
) << 32;
603 db
->mask
= le32_to_cpu(resp
->db_preserve_lmask
);
604 db
->mask
|= (u64
)le32_to_cpu(resp
->db_preserve_hmask
) << 32;
608 scmi_xfer_put(handle
, t
);
611 static void scmi_perf_domain_init_fc(const struct scmi_handle
*handle
,
612 u32 domain
, struct scmi_fc_info
**p_fc
)
614 struct scmi_fc_info
*fc
;
616 fc
= devm_kzalloc(handle
->dev
, sizeof(*fc
), GFP_KERNEL
);
620 scmi_perf_domain_desc_fc(handle
, domain
, PERF_LEVEL_SET
,
621 &fc
->level_set_addr
, &fc
->level_set_db
);
622 scmi_perf_domain_desc_fc(handle
, domain
, PERF_LEVEL_GET
,
623 &fc
->level_get_addr
, NULL
);
624 scmi_perf_domain_desc_fc(handle
, domain
, PERF_LIMITS_SET
,
625 &fc
->limit_set_addr
, &fc
->limit_set_db
);
626 scmi_perf_domain_desc_fc(handle
, domain
, PERF_LIMITS_GET
,
627 &fc
->limit_get_addr
, NULL
);
631 /* Device specific ops */
632 static int scmi_dev_domain_id(struct device
*dev
)
634 struct of_phandle_args clkspec
;
636 if (of_parse_phandle_with_args(dev
->of_node
, "clocks", "#clock-cells",
640 return clkspec
.args
[0];
643 static int scmi_dvfs_device_opps_add(const struct scmi_handle
*handle
,
646 int idx
, ret
, domain
;
648 struct scmi_opp
*opp
;
649 struct perf_dom_info
*dom
;
650 struct scmi_perf_info
*pi
= handle
->perf_priv
;
652 domain
= scmi_dev_domain_id(dev
);
656 dom
= pi
->dom_info
+ domain
;
658 for (opp
= dom
->opp
, idx
= 0; idx
< dom
->opp_count
; idx
++, opp
++) {
659 freq
= opp
->perf
* dom
->mult_factor
;
661 ret
= dev_pm_opp_add(dev
, freq
, 0);
663 dev_warn(dev
, "failed to add opp %luHz\n", freq
);
666 freq
= (--opp
)->perf
* dom
->mult_factor
;
667 dev_pm_opp_remove(dev
, freq
);
675 static int scmi_dvfs_transition_latency_get(const struct scmi_handle
*handle
,
678 struct perf_dom_info
*dom
;
679 struct scmi_perf_info
*pi
= handle
->perf_priv
;
680 int domain
= scmi_dev_domain_id(dev
);
685 dom
= pi
->dom_info
+ domain
;
687 return dom
->opp
[dom
->opp_count
- 1].trans_latency_us
* 1000;
690 static int scmi_dvfs_freq_set(const struct scmi_handle
*handle
, u32 domain
,
691 unsigned long freq
, bool poll
)
693 struct scmi_perf_info
*pi
= handle
->perf_priv
;
694 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
696 return scmi_perf_level_set(handle
, domain
, freq
/ dom
->mult_factor
,
700 static int scmi_dvfs_freq_get(const struct scmi_handle
*handle
, u32 domain
,
701 unsigned long *freq
, bool poll
)
705 struct scmi_perf_info
*pi
= handle
->perf_priv
;
706 struct perf_dom_info
*dom
= pi
->dom_info
+ domain
;
708 ret
= scmi_perf_level_get(handle
, domain
, &level
, poll
);
710 *freq
= level
* dom
->mult_factor
;
715 static int scmi_dvfs_est_power_get(const struct scmi_handle
*handle
, u32 domain
,
716 unsigned long *freq
, unsigned long *power
)
718 struct scmi_perf_info
*pi
= handle
->perf_priv
;
719 struct perf_dom_info
*dom
;
720 unsigned long opp_freq
;
721 int idx
, ret
= -EINVAL
;
722 struct scmi_opp
*opp
;
724 dom
= pi
->dom_info
+ domain
;
728 for (opp
= dom
->opp
, idx
= 0; idx
< dom
->opp_count
; idx
++, opp
++) {
729 opp_freq
= opp
->perf
* dom
->mult_factor
;
730 if (opp_freq
< *freq
)
742 static bool scmi_fast_switch_possible(const struct scmi_handle
*handle
,
745 struct perf_dom_info
*dom
;
746 struct scmi_perf_info
*pi
= handle
->perf_priv
;
748 dom
= pi
->dom_info
+ scmi_dev_domain_id(dev
);
750 return dom
->fc_info
&& dom
->fc_info
->level_set_addr
;
753 static bool scmi_power_scale_mw_get(const struct scmi_handle
*handle
)
755 struct scmi_perf_info
*pi
= handle
->perf_priv
;
757 return pi
->power_scale_mw
;
760 static const struct scmi_perf_ops perf_ops
= {
761 .limits_set
= scmi_perf_limits_set
,
762 .limits_get
= scmi_perf_limits_get
,
763 .level_set
= scmi_perf_level_set
,
764 .level_get
= scmi_perf_level_get
,
765 .device_domain_id
= scmi_dev_domain_id
,
766 .transition_latency_get
= scmi_dvfs_transition_latency_get
,
767 .device_opps_add
= scmi_dvfs_device_opps_add
,
768 .freq_set
= scmi_dvfs_freq_set
,
769 .freq_get
= scmi_dvfs_freq_get
,
770 .est_power_get
= scmi_dvfs_est_power_get
,
771 .fast_switch_possible
= scmi_fast_switch_possible
,
772 .power_scale_mw_get
= scmi_power_scale_mw_get
,
775 static int scmi_perf_set_notify_enabled(const struct scmi_handle
*handle
,
776 u8 evt_id
, u32 src_id
, bool enable
)
780 if (evt_id
>= ARRAY_SIZE(evt_2_cmd
))
783 cmd_id
= evt_2_cmd
[evt_id
];
784 ret
= scmi_perf_level_limits_notify(handle
, src_id
, cmd_id
, enable
);
786 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
787 evt_id
, src_id
, ret
);
792 static void *scmi_perf_fill_custom_report(const struct scmi_handle
*handle
,
793 u8 evt_id
, ktime_t timestamp
,
794 const void *payld
, size_t payld_sz
,
795 void *report
, u32
*src_id
)
800 case SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED
:
802 const struct scmi_perf_limits_notify_payld
*p
= payld
;
803 struct scmi_perf_limits_report
*r
= report
;
805 if (sizeof(*p
) != payld_sz
)
808 r
->timestamp
= timestamp
;
809 r
->agent_id
= le32_to_cpu(p
->agent_id
);
810 r
->domain_id
= le32_to_cpu(p
->domain_id
);
811 r
->range_max
= le32_to_cpu(p
->range_max
);
812 r
->range_min
= le32_to_cpu(p
->range_min
);
813 *src_id
= r
->domain_id
;
817 case SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED
:
819 const struct scmi_perf_level_notify_payld
*p
= payld
;
820 struct scmi_perf_level_report
*r
= report
;
822 if (sizeof(*p
) != payld_sz
)
825 r
->timestamp
= timestamp
;
826 r
->agent_id
= le32_to_cpu(p
->agent_id
);
827 r
->domain_id
= le32_to_cpu(p
->domain_id
);
828 r
->performance_level
= le32_to_cpu(p
->performance_level
);
829 *src_id
= r
->domain_id
;
840 static const struct scmi_event perf_events
[] = {
842 .id
= SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED
,
843 .max_payld_sz
= sizeof(struct scmi_perf_limits_notify_payld
),
844 .max_report_sz
= sizeof(struct scmi_perf_limits_report
),
847 .id
= SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED
,
848 .max_payld_sz
= sizeof(struct scmi_perf_level_notify_payld
),
849 .max_report_sz
= sizeof(struct scmi_perf_level_report
),
853 static const struct scmi_event_ops perf_event_ops
= {
854 .set_notify_enabled
= scmi_perf_set_notify_enabled
,
855 .fill_custom_report
= scmi_perf_fill_custom_report
,
858 static int scmi_perf_protocol_init(struct scmi_handle
*handle
)
862 struct scmi_perf_info
*pinfo
;
864 scmi_version_get(handle
, SCMI_PROTOCOL_PERF
, &version
);
866 dev_dbg(handle
->dev
, "Performance Version %d.%d\n",
867 PROTOCOL_REV_MAJOR(version
), PROTOCOL_REV_MINOR(version
));
869 pinfo
= devm_kzalloc(handle
->dev
, sizeof(*pinfo
), GFP_KERNEL
);
873 scmi_perf_attributes_get(handle
, pinfo
);
875 pinfo
->dom_info
= devm_kcalloc(handle
->dev
, pinfo
->num_domains
,
876 sizeof(*pinfo
->dom_info
), GFP_KERNEL
);
877 if (!pinfo
->dom_info
)
880 for (domain
= 0; domain
< pinfo
->num_domains
; domain
++) {
881 struct perf_dom_info
*dom
= pinfo
->dom_info
+ domain
;
883 scmi_perf_domain_attributes_get(handle
, domain
, dom
);
884 scmi_perf_describe_levels_get(handle
, domain
, dom
);
886 if (dom
->perf_fastchannels
)
887 scmi_perf_domain_init_fc(handle
, domain
, &dom
->fc_info
);
890 scmi_register_protocol_events(handle
,
891 SCMI_PROTOCOL_PERF
, SCMI_PROTO_QUEUE_SZ
,
892 &perf_event_ops
, perf_events
,
893 ARRAY_SIZE(perf_events
),
896 pinfo
->version
= version
;
897 handle
->perf_ops
= &perf_ops
;
898 handle
->perf_priv
= pinfo
;
903 DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(SCMI_PROTOCOL_PERF
, perf
)