Skip to content

Commit 2441caa

Browse files
pierregondoisvireshk
authored andcommitted
firmware: arm_scmi: Populate fast channel rate_limit
Arm SCMI spec. v3.2, s4.5.3.12 PERFORMANCE_DESCRIBE_FASTCHANNEL defines a per-domain rate_limit for performance requests: """ Rate Limit in microseconds, indicating the minimum time required between successive requests. A value of 0 indicates that this field is not applicable or supported on the platform. """" The field is first defined in SCMI v2.0. Add support to fetch this value and advertise it through a fast_switch_rate_limit() callback. Signed-off-by: Pierre Gondois <pierre.gondois@arm.com> Reviewed-by: Cristian Marussi <cristian.marussi@arm.com> Acked-by: Sudeep Holla <sudeep.holla@arm.com> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
1 parent ad86f7e commit 2441caa

File tree

5 files changed

+47
-10
lines changed

5 files changed

+47
-10
lines changed

drivers/firmware/arm_scmi/driver.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1617,7 +1617,7 @@ static void
16171617
scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
16181618
u8 describe_id, u32 message_id, u32 valid_size,
16191619
u32 domain, void __iomem **p_addr,
1620-
struct scmi_fc_db_info **p_db)
1620+
struct scmi_fc_db_info **p_db, u32 *rate_limit)
16211621
{
16221622
int ret;
16231623
u32 flags;
@@ -1661,6 +1661,9 @@ scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
16611661
goto err_xfer;
16621662
}
16631663

1664+
if (rate_limit)
1665+
*rate_limit = le32_to_cpu(resp->rate_limit) & GENMASK(19, 0);
1666+
16641667
phys_addr = le32_to_cpu(resp->chan_addr_low);
16651668
phys_addr |= (u64)le32_to_cpu(resp->chan_addr_high) << 32;
16661669
addr = devm_ioremap(ph->dev, phys_addr, size);

drivers/firmware/arm_scmi/perf.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -776,23 +776,27 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
776776

777777
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
778778
PERF_LEVEL_GET, 4, dom->id,
779-
&fc[PERF_FC_LEVEL].get_addr, NULL);
779+
&fc[PERF_FC_LEVEL].get_addr, NULL,
780+
&fc[PERF_FC_LEVEL].rate_limit);
780781

781782
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
782783
PERF_LIMITS_GET, 8, dom->id,
783-
&fc[PERF_FC_LIMIT].get_addr, NULL);
784+
&fc[PERF_FC_LIMIT].get_addr, NULL,
785+
&fc[PERF_FC_LIMIT].rate_limit);
784786

785787
if (dom->info.set_perf)
786788
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
787789
PERF_LEVEL_SET, 4, dom->id,
788790
&fc[PERF_FC_LEVEL].set_addr,
789-
&fc[PERF_FC_LEVEL].set_db);
791+
&fc[PERF_FC_LEVEL].set_db,
792+
&fc[PERF_FC_LEVEL].rate_limit);
790793

791794
if (dom->set_limits)
792795
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
793796
PERF_LIMITS_SET, 8, dom->id,
794797
&fc[PERF_FC_LIMIT].set_addr,
795-
&fc[PERF_FC_LIMIT].set_db);
798+
&fc[PERF_FC_LIMIT].set_db,
799+
&fc[PERF_FC_LIMIT].rate_limit);
796800

797801
dom->fc_info = fc;
798802
}
@@ -961,6 +965,25 @@ static bool scmi_fast_switch_possible(const struct scmi_protocol_handle *ph,
961965
return dom->fc_info && dom->fc_info[PERF_FC_LEVEL].set_addr;
962966
}
963967

968+
static int scmi_fast_switch_rate_limit(const struct scmi_protocol_handle *ph,
969+
u32 domain, u32 *rate_limit)
970+
{
971+
struct perf_dom_info *dom;
972+
973+
if (!rate_limit)
974+
return -EINVAL;
975+
976+
dom = scmi_perf_domain_lookup(ph, domain);
977+
if (IS_ERR(dom))
978+
return PTR_ERR(dom);
979+
980+
if (!dom->fc_info)
981+
return -EINVAL;
982+
983+
*rate_limit = dom->fc_info[PERF_FC_LEVEL].rate_limit;
984+
return 0;
985+
}
986+
964987
static enum scmi_power_scale
965988
scmi_power_scale_get(const struct scmi_protocol_handle *ph)
966989
{
@@ -983,6 +1006,7 @@ static const struct scmi_perf_proto_ops perf_proto_ops = {
9831006
.freq_get = scmi_dvfs_freq_get,
9841007
.est_power_get = scmi_dvfs_est_power_get,
9851008
.fast_switch_possible = scmi_fast_switch_possible,
1009+
.fast_switch_rate_limit = scmi_fast_switch_rate_limit,
9861010
.power_scale_get = scmi_power_scale_get,
9871011
};
9881012

drivers/firmware/arm_scmi/powercap.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -703,20 +703,24 @@ static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
703703
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
704704
POWERCAP_CAP_SET, 4, domain,
705705
&fc[POWERCAP_FC_CAP].set_addr,
706-
&fc[POWERCAP_FC_CAP].set_db);
706+
&fc[POWERCAP_FC_CAP].set_db,
707+
&fc[POWERCAP_FC_CAP].rate_limit);
707708

708709
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
709710
POWERCAP_CAP_GET, 4, domain,
710-
&fc[POWERCAP_FC_CAP].get_addr, NULL);
711+
&fc[POWERCAP_FC_CAP].get_addr, NULL,
712+
&fc[POWERCAP_FC_CAP].rate_limit);
711713

712714
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
713715
POWERCAP_PAI_SET, 4, domain,
714716
&fc[POWERCAP_FC_PAI].set_addr,
715-
&fc[POWERCAP_FC_PAI].set_db);
717+
&fc[POWERCAP_FC_PAI].set_db,
718+
&fc[POWERCAP_FC_PAI].rate_limit);
716719

717720
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
718721
POWERCAP_PAI_GET, 4, domain,
719-
&fc[POWERCAP_FC_PAI].get_addr, NULL);
722+
&fc[POWERCAP_FC_PAI].get_addr, NULL,
723+
&fc[POWERCAP_PAI_GET].rate_limit);
720724

721725
*p_fc = fc;
722726
}

drivers/firmware/arm_scmi/protocols.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ struct scmi_fc_info {
234234
void __iomem *set_addr;
235235
void __iomem *get_addr;
236236
struct scmi_fc_db_info *set_db;
237+
u32 rate_limit;
237238
};
238239

239240
/**
@@ -268,7 +269,8 @@ struct scmi_proto_helpers_ops {
268269
u8 describe_id, u32 message_id,
269270
u32 valid_size, u32 domain,
270271
void __iomem **p_addr,
271-
struct scmi_fc_db_info **p_db);
272+
struct scmi_fc_db_info **p_db,
273+
u32 *rate_limit);
272274
void (*fastchannel_db_ring)(struct scmi_fc_db_info *db);
273275
};
274276

include/linux/scmi_protocol.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ struct scmi_perf_domain_info {
139139
* at a given frequency
140140
* @fast_switch_possible: indicates if fast DVFS switching is possible or not
141141
* for a given device
142+
* @fast_switch_rate_limit: gets the minimum time (us) required between
143+
* successive fast_switching requests
142144
* @power_scale_mw_get: indicates if the power values provided are in milliWatts
143145
* or in some other (abstract) scale
144146
*/
@@ -168,6 +170,8 @@ struct scmi_perf_proto_ops {
168170
unsigned long *rate, unsigned long *power);
169171
bool (*fast_switch_possible)(const struct scmi_protocol_handle *ph,
170172
u32 domain);
173+
int (*fast_switch_rate_limit)(const struct scmi_protocol_handle *ph,
174+
u32 domain, u32 *rate_limit);
171175
enum scmi_power_scale (*power_scale_get)(const struct scmi_protocol_handle *ph);
172176
};
173177

0 commit comments

Comments
 (0)