History

firmware: arm_scmi: Add SCMI v3.1 clock notifications

Add SCMI v3.1 clock pre and post notifications.

Cristian Marussi committed 4 years ago

Commit 7aa75491 parent 71bea052 files · +142 −5Browse files

Unified · Split

2 files
  1. drivers/firmware/arm_scmi/clock.c +131 −5
  2. include/linux/scmi_protocol.h +11 −0
drivers/firmware/arm_scmi/clock.c+131−5
@@ -10,6 +10,7 @@ · 9 unmodified lines
10#include <linux/sort.h>10#include <linux/sort.h>
11 11
12#include "protocols.h"12#include "protocols.h"
13#include "notify.h"
13 14
14enum scmi_clock_protocol_cmd {15enum scmi_clock_protocol_cmd {
15 CLOCK_ATTRIBUTES = 0x3,16 CLOCK_ATTRIBUTES = 0x3,
@@ -18,6 +19,8 @@ enum scmi_clock_protocol_cmd { · 2 unmodified lines
18 CLOCK_RATE_GET = 0x6,19 CLOCK_RATE_GET = 0x6,
19 CLOCK_CONFIG_SET = 0x7,20 CLOCK_CONFIG_SET = 0x7,
20 CLOCK_NAME_GET = 0x8,21 CLOCK_NAME_GET = 0x8,
22 CLOCK_RATE_NOTIFY = 0x9,
23 CLOCK_RATE_CHANGE_REQUESTED_NOTIFY = 0xA,
21};24};
22 25
23struct scmi_msg_resp_clock_protocol_attributes {26struct scmi_msg_resp_clock_protocol_attributes {
@@ -29,7 +32,9 @@ struct scmi_msg_resp_clock_protocol_attributes { · 5 unmodified lines
29struct scmi_msg_resp_clock_attributes {32struct scmi_msg_resp_clock_attributes {
30 __le32 attributes;33 __le32 attributes;
31#define CLOCK_ENABLE BIT(0)34#define CLOCK_ENABLE BIT(0)
32#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29))35#define SUPPORTS_RATE_CHANGED_NOTIF(x) ((x) & BIT(31))
36#define SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(x) ((x) & BIT(30))
37#define SUPPORTS_EXTENDED_NAMES(x) ((x) & BIT(29))
33 u8 name[SCMI_SHORT_NAME_MAX_SIZE];38 u8 name[SCMI_SHORT_NAME_MAX_SIZE];
34 __le32 clock_enable_latency;39 __le32 clock_enable_latency;
35};40};
@@ -77,6 +82,18 @@ struct scmi_msg_resp_set_rate_complete { · 41 unmodified lines
77 __le32 rate_high;82 __le32 rate_high;
78};83};
79 84
85struct scmi_msg_clock_rate_notify {
86 __le32 clk_id;
87 __le32 notify_enable;
88};
89
90struct scmi_clock_rate_notify_payld {
91 __le32 agent_id;
92 __le32 clock_id;
93 __le32 rate_low;
94 __le32 rate_high;
95};
96
80struct clock_info {97struct clock_info {
81 u32 version;98 u32 version;
82 int num_clocks;99 int num_clocks;
@@ -85,6 +102,11 @@ struct clock_info { · 2 unmodified lines
85 struct scmi_clock_info *clk;102 struct scmi_clock_info *clk;
86};103};
87 104
105static enum scmi_clock_protocol_cmd evt_2_cmd[] = {
106 CLOCK_RATE_NOTIFY,
107 CLOCK_RATE_CHANGE_REQUESTED_NOTIFY,
108};
109
88static int110static int
89scmi_clock_protocol_attributes_get(const struct scmi_protocol_handle *ph,111scmi_clock_protocol_attributes_get(const struct scmi_protocol_handle *ph,
90 struct clock_info *ci)112 struct clock_info *ci)
@@ -144,10 +166,17 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph, · 53 unmodified lines
144 * If supported overwrite short name with the extended one;166 * If supported overwrite short name with the extended one;
145 * on error just carry on and use already provided short name.167 * on error just carry on and use already provided short name.
146 */168 */
147 if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x2 &&169 if (!ret && PROTOCOL_REV_MAJOR(version) >= 0x2) {
148 SUPPORTS_EXTENDED_NAMES(attributes))170 if (SUPPORTS_EXTENDED_NAMES(attributes))
149 ph->hops->extended_name_get(ph, CLOCK_NAME_GET, clk_id,171 ph->hops->extended_name_get(ph, CLOCK_NAME_GET, clk_id,
150 clk->name, SCMI_MAX_STR_SIZE);172 clk->name,
173 SCMI_MAX_STR_SIZE);
174
175 if (SUPPORTS_RATE_CHANGED_NOTIF(attributes))
176 clk->rate_changed_notifications = true;
177 if (SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(attributes))
178 clk->rate_change_requested_notifications = true;
179 }
151 180
152 return ret;181 return ret;
153}182}
@@ -418,6 +447,102 @@ static const struct scmi_clk_proto_ops clk_proto_ops = { · 264 unmodified lines
418 .disable_atomic = scmi_clock_disable_atomic,447 .disable_atomic = scmi_clock_disable_atomic,
419};448};
420 449
450static int scmi_clk_rate_notify(const struct scmi_protocol_handle *ph,
451 u32 clk_id, int message_id, bool enable)
452{
453 int ret;
454 struct scmi_xfer *t;
455 struct scmi_msg_clock_rate_notify *notify;
456
457 ret = ph->xops->xfer_get_init(ph, message_id, sizeof(*notify), 0, &t);
458 if (ret)
459 return ret;
460
461 notify = t->tx.buf;
462 notify->clk_id = cpu_to_le32(clk_id);
463 notify->notify_enable = enable ? cpu_to_le32(BIT(0)) : 0;
464
465 ret = ph->xops->do_xfer(ph, t);
466
467 ph->xops->xfer_put(ph, t);
468 return ret;
469}
470
471static int scmi_clk_set_notify_enabled(const struct scmi_protocol_handle *ph,
472 u8 evt_id, u32 src_id, bool enable)
473{
474 int ret, cmd_id;
475
476 if (evt_id >= ARRAY_SIZE(evt_2_cmd))
477 return -EINVAL;
478
479 cmd_id = evt_2_cmd[evt_id];
480 ret = scmi_clk_rate_notify(ph, src_id, cmd_id, enable);
481 if (ret)
482 pr_debug("FAIL_ENABLED - evt[%X] dom[%d] - ret:%d\n",
483 evt_id, src_id, ret);
484
485 return ret;
486}
487
488static void *scmi_clk_fill_custom_report(const struct scmi_protocol_handle *ph,
489 u8 evt_id, ktime_t timestamp,
490 const void *payld, size_t payld_sz,
491 void *report, u32 *src_id)
492{
493 const struct scmi_clock_rate_notify_payld *p = payld;
494 struct scmi_clock_rate_notif_report *r = report;
495
496 if (sizeof(*p) != payld_sz ||
497 (evt_id != SCMI_EVENT_CLOCK_RATE_CHANGED &&
498 evt_id != SCMI_EVENT_CLOCK_RATE_CHANGE_REQUESTED))
499 return NULL;
500
501 r->timestamp = timestamp;
502 r->agent_id = le32_to_cpu(p->agent_id);
503 r->clock_id = le32_to_cpu(p->clock_id);
504 r->rate = get_unaligned_le64(&p->rate_low);
505 *src_id = r->clock_id;
506
507 return r;
508}
509
510static int scmi_clk_get_num_sources(const struct scmi_protocol_handle *ph)
511{
512 struct clock_info *ci = ph->get_priv(ph);
513
514 if (!ci)
515 return -EINVAL;
516
517 return ci->num_clocks;
518}
519
520static const struct scmi_event clk_events[] = {
521 {
522 .id = SCMI_EVENT_CLOCK_RATE_CHANGED,
523 .max_payld_sz = sizeof(struct scmi_clock_rate_notify_payld),
524 .max_report_sz = sizeof(struct scmi_clock_rate_notif_report),
525 },
526 {
527 .id = SCMI_EVENT_CLOCK_RATE_CHANGE_REQUESTED,
528 .max_payld_sz = sizeof(struct scmi_clock_rate_notify_payld),
529 .max_report_sz = sizeof(struct scmi_clock_rate_notif_report),
530 },
531};
532
533static const struct scmi_event_ops clk_event_ops = {
534 .get_num_sources = scmi_clk_get_num_sources,
535 .set_notify_enabled = scmi_clk_set_notify_enabled,
536 .fill_custom_report = scmi_clk_fill_custom_report,
537};
538
539static const struct scmi_protocol_events clk_protocol_events = {
540 .queue_sz = SCMI_PROTO_QUEUE_SZ,
541 .ops = &clk_event_ops,
542 .evts = clk_events,
543 .num_events = ARRAY_SIZE(clk_events),
544};
545
421static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)546static int scmi_clock_protocol_init(const struct scmi_protocol_handle *ph)
422{547{
423 u32 version;548 u32 version;
@@ -461,6 +586,7 @@ static const struct scmi_protocol scmi_clock = { · 37 unmodified lines
461 .owner = THIS_MODULE,586 .owner = THIS_MODULE,
462 .instance_init = &scmi_clock_protocol_init,587 .instance_init = &scmi_clock_protocol_init,
463 .ops = &clk_proto_ops,588 .ops = &clk_proto_ops,
589 .events = &clk_protocol_events,
464};590};
465 591
466DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(clock, scmi_clock)592DEFINE_SCMI_PROTOCOL_REGISTER_UNREGISTER(clock, scmi_clock)
include/linux/scmi_protocol.h+11−0
@@ -44,6 +44,8 @@ struct scmi_clock_info { · 43 unmodified lines
44 char name[SCMI_MAX_STR_SIZE];44 char name[SCMI_MAX_STR_SIZE];
45 unsigned int enable_latency;45 unsigned int enable_latency;
46 bool rate_discrete;46 bool rate_discrete;
47 bool rate_changed_notifications;
48 bool rate_change_requested_notifications;
47 union {49 union {
48 struct {50 struct {
49 int num_rates;51 int num_rates;
@@ -744,6 +746,8 @@ void scmi_protocol_unregister(const struct scmi_protocol *proto); · 694 unmodified lines
744/* SCMI Notification API - Custom Event Reports */746/* SCMI Notification API - Custom Event Reports */
745enum scmi_notification_events {747enum scmi_notification_events {
746 SCMI_EVENT_POWER_STATE_CHANGED = 0x0,748 SCMI_EVENT_POWER_STATE_CHANGED = 0x0,
749 SCMI_EVENT_CLOCK_RATE_CHANGED = 0x0,
750 SCMI_EVENT_CLOCK_RATE_CHANGE_REQUESTED = 0x1,
747 SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED = 0x0,751 SCMI_EVENT_PERFORMANCE_LIMITS_CHANGED = 0x0,
748 SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED = 0x1,752 SCMI_EVENT_PERFORMANCE_LEVEL_CHANGED = 0x1,
749 SCMI_EVENT_SENSOR_TRIP_POINT_EVENT = 0x0,753 SCMI_EVENT_SENSOR_TRIP_POINT_EVENT = 0x0,
@@ -760,6 +764,13 @@ struct scmi_power_state_changed_report { · 10 unmodified lines
760 unsigned int power_state;764 unsigned int power_state;
761};765};
762 766
767struct scmi_clock_rate_notif_report {
768 ktime_t timestamp;
769 unsigned int agent_id;
770 unsigned int clock_id;
771 unsigned long long rate;
772};
773
763struct scmi_system_power_state_notifier_report {774struct scmi_system_power_state_notifier_report {
764 ktime_t timestamp;775 ktime_t timestamp;
765 unsigned int agent_id;776 unsigned int agent_id;