* [PATCH v6 05/12] firmware: arm_scmi: Add SCMIV4.0 Powercap notifications support
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Extend notification support to the new SCMIv4.0 Powercap format that carry
also a CPL identifier where specified.
Since this addition completes SCMIv4.0 Powercap support bump also the
protocol version define.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/firmware/arm_scmi/powercap.c | 13 +++++++++----
include/linux/scmi_protocol.h | 3 ++-
2 files changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index db5bc4f38ea4..1d1188e98d49 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -18,7 +18,7 @@
#include "notify.h"
/* Updated only after ALL the mandatory features for that version are merged */
-#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
+#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x30000
#define CPL0 0
@@ -156,7 +156,8 @@ struct scmi_powercap_cap_changed_notify_payld {
__le32 agent_id;
__le32 domain_id;
__le32 power_cap;
- __le32 pai;
+ __le32 avg_ivl;
+ __le32 cpli;
};
struct scmi_powercap_meas_changed_notify_payld {
@@ -1312,14 +1313,18 @@ scmi_powercap_fill_custom_report(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_cap_changed_notify_payld *p = payld;
struct scmi_powercap_cap_changed_report *r = report;
- if (sizeof(*p) != payld_sz)
+ if (sizeof(*p) > payld_sz)
break;
r->timestamp = timestamp;
r->agent_id = le32_to_cpu(p->agent_id);
r->domain_id = le32_to_cpu(p->domain_id);
r->power_cap = le32_to_cpu(p->power_cap);
- r->pai = le32_to_cpu(p->pai);
+ r->avg_ivl = le32_to_cpu(p->avg_ivl);
+ if (sizeof(*p) == payld_sz)
+ r->cpli = le32_to_cpu(p->cpli);
+ else
+ r->cpli = 0;
*src_id = r->domain_id;
rep = r;
break;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index 547ab4763a63..299fa8499b3f 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -1125,7 +1125,8 @@ struct scmi_powercap_cap_changed_report {
unsigned int agent_id;
unsigned int domain_id;
unsigned int power_cap;
- unsigned int pai;
+ unsigned int avg_ivl;
+ unsigned int cpli;
};
struct scmi_powercap_meas_changed_report {
--
2.47.3
^ permalink raw reply related
* [PATCH v6 02/12] firmware: arm_scmi: Refactor powercap domain layout
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
SCMIv4.0 introduces the idea of an optional Concurrent Power Limit (CPL)
for each powercap domain, where CPL0 coincides with the one and only
per-domain constraint limit that was available in pre-v4.0 SCMI Powercap.
Refactor the powercap domain descriptors and powercap operations to allow
future v4.0 extensions to cope with multiple CPLs.
While at that generalize the powercap protocol API to drop PAI references
in favour of a more generic avg_ivl naming, since from v4.0 the number and
types of averaging intervals will change in a non-backward compatible way,
so let's bury these changes within the protocol layer.
Last but not least, make the necessary changes to the ARM SCMI Powwercap
driver in order to support all of these new capabilities.
No functional change.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
[Philip: Adjusted domain_id comparitor in scmi_powercap_pai_get]
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/firmware/arm_scmi/powercap.c | 182 +++++++++++++++++----------
drivers/powercap/arm_scmi_powercap.c | 50 ++++----
include/linux/scmi_protocol.h | 74 +++++++----
3 files changed, 188 insertions(+), 118 deletions(-)
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index 22aff71c75e9..47aa6dde4a52 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -2,7 +2,7 @@
/*
* System Control and Management Interface (SCMI) Powercap Protocol
*
- * Copyright (C) 2022 ARM Ltd.
+ * Copyright (C) 2022-2026 ARM Ltd.
*/
#define pr_fmt(fmt) "SCMI Notifications POWERCAP - " fmt
@@ -20,6 +20,8 @@
/* Updated only after ALL the mandatory features for that version are merged */
#define SCMI_PROTOCOL_SUPPORTED_VERSION 0x20000
+#define CPL0 0
+
enum scmi_powercap_protocol_cmd {
POWERCAP_DOMAIN_ATTRIBUTES = 0x3,
POWERCAP_CAP_GET = 0x4,
@@ -192,27 +194,26 @@ scmi_powercap_validate(unsigned int min_val, unsigned int max_val,
static int
scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
- struct powercap_info *pinfo, u32 domain)
+ struct powercap_info *pinfo,
+ struct scmi_powercap_info *dom_info)
{
int ret;
u32 flags;
struct scmi_xfer *t;
- struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
struct scmi_msg_resp_powercap_domain_attributes *resp;
ret = ph->xops->xfer_get_init(ph, POWERCAP_DOMAIN_ATTRIBUTES,
- sizeof(domain), sizeof(*resp), &t);
+ sizeof(dom_info->id), sizeof(*resp), &t);
if (ret)
return ret;
- put_unaligned_le32(domain, t->tx.buf);
+ put_unaligned_le32(dom_info->id, t->tx.buf);
resp = t->rx.buf;
ret = ph->xops->do_xfer(ph, t);
if (!ret) {
flags = le32_to_cpu(resp->attributes);
- dom_info->id = domain;
if (pinfo->notify_cap_cmd)
dom_info->notify_powercap_cap_change =
SUPPORTS_POWERCAP_CAP_CHANGE_NOTIFY(flags);
@@ -221,12 +222,9 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
SUPPORTS_POWERCAP_MEASUREMENTS_CHANGE_NOTIFY(flags);
dom_info->async_powercap_cap_set =
SUPPORTS_ASYNC_POWERCAP_CAP_SET(flags);
- dom_info->powercap_cap_config =
- SUPPORTS_POWERCAP_CAP_CONFIGURATION(flags);
+
dom_info->powercap_monitoring =
SUPPORTS_POWERCAP_MONITORING(flags);
- dom_info->powercap_pai_config =
- SUPPORTS_POWERCAP_PAI_CONFIGURATION(flags);
dom_info->powercap_scale_mw =
SUPPORTS_POWER_UNITS_MW(flags);
dom_info->powercap_scale_uw =
@@ -236,13 +234,29 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
strscpy(dom_info->name, resp->name, SCMI_SHORT_NAME_MAX_SIZE);
- dom_info->min_pai = le32_to_cpu(resp->min_pai);
- dom_info->max_pai = le32_to_cpu(resp->max_pai);
- dom_info->pai_step = le32_to_cpu(resp->pai_step);
- ret = scmi_powercap_validate(dom_info->min_pai,
- dom_info->max_pai,
- dom_info->pai_step,
- dom_info->powercap_pai_config);
+ dom_info->sustainable_power =
+ le32_to_cpu(resp->sustainable_power);
+ dom_info->accuracy = le32_to_cpu(resp->accuracy);
+
+ dom_info->parent_id = le32_to_cpu(resp->parent_id);
+ if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID &&
+ (dom_info->parent_id >= pinfo->num_domains ||
+ dom_info->parent_id == dom_info->id)) {
+ dev_err(ph->dev,
+ "Platform reported inconsistent parent ID for domain %d - %s\n",
+ dom_info->id, dom_info->name);
+ ret = -ENODEV;
+ }
+
+ dom_info->cpli[0].avg_ivl_config =
+ SUPPORTS_POWERCAP_PAI_CONFIGURATION(flags);
+ dom_info->cpli[0].min_avg_ivl = le32_to_cpu(resp->min_pai);
+ dom_info->cpli[0].max_avg_ivl = le32_to_cpu(resp->max_pai);
+ dom_info->cpli[0].avg_ivl_step = le32_to_cpu(resp->pai_step);
+ ret = scmi_powercap_validate(dom_info->cpli[0].min_avg_ivl,
+ dom_info->cpli[0].max_avg_ivl,
+ dom_info->cpli[0].avg_ivl_step,
+ dom_info->cpli[0].avg_ivl_config);
if (ret) {
dev_err(ph->dev,
"Platform reported inconsistent PAI config for domain %d - %s\n",
@@ -250,13 +264,15 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
goto clean;
}
- dom_info->min_power_cap = le32_to_cpu(resp->min_power_cap);
- dom_info->max_power_cap = le32_to_cpu(resp->max_power_cap);
- dom_info->power_cap_step = le32_to_cpu(resp->power_cap_step);
- ret = scmi_powercap_validate(dom_info->min_power_cap,
- dom_info->max_power_cap,
- dom_info->power_cap_step,
- dom_info->powercap_cap_config);
+ dom_info->cpli[0].cap_config =
+ SUPPORTS_POWERCAP_CAP_CONFIGURATION(flags);
+ dom_info->cpli[0].min_power_cap = le32_to_cpu(resp->min_power_cap);
+ dom_info->cpli[0].max_power_cap = le32_to_cpu(resp->max_power_cap);
+ dom_info->cpli[0].power_cap_step = le32_to_cpu(resp->power_cap_step);
+ ret = scmi_powercap_validate(dom_info->cpli[0].min_power_cap,
+ dom_info->cpli[0].max_power_cap,
+ dom_info->cpli[0].power_cap_step,
+ dom_info->cpli[0].cap_config);
if (ret) {
dev_err(ph->dev,
"Platform reported inconsistent CAP config for domain %d - %s\n",
@@ -264,19 +280,9 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
goto clean;
}
- dom_info->sustainable_power =
- le32_to_cpu(resp->sustainable_power);
- dom_info->accuracy = le32_to_cpu(resp->accuracy);
-
- dom_info->parent_id = le32_to_cpu(resp->parent_id);
- if (dom_info->parent_id != SCMI_POWERCAP_ROOT_ZONE_ID &&
- (dom_info->parent_id >= pinfo->num_domains ||
- dom_info->parent_id == dom_info->id)) {
- dev_err(ph->dev,
- "Platform reported inconsistent parent ID for domain %d - %s\n",
- dom_info->id, dom_info->name);
- ret = -ENODEV;
- }
+ /* Just using same short name */
+ strscpy(dom_info->cpli[0].name, dom_info->name,
+ SCMI_SHORT_NAME_MAX_SIZE);
}
clean:
@@ -288,12 +294,30 @@ scmi_powercap_domain_attributes_get(const struct scmi_protocol_handle *ph,
*/
if (!ret && SUPPORTS_EXTENDED_NAMES(flags))
ph->hops->extended_name_get(ph, POWERCAP_DOMAIN_NAME_GET,
- domain, NULL, dom_info->name,
+ dom_info->id, NULL, dom_info->name,
SCMI_MAX_STR_SIZE);
return ret;
}
+static int
+scmi_powercap_domain_initialize(const struct scmi_protocol_handle *ph,
+ struct powercap_info *pinfo, u32 domain)
+{
+ struct scmi_powercap_info *dom_info = pinfo->powercaps + domain;
+
+ dom_info->num_cpli = 1;
+ dom_info->cpli = devm_kcalloc(ph->dev, dom_info->num_cpli,
+ sizeof(*dom_info->cpli), GFP_KERNEL);
+ if (!dom_info->cpli)
+ return -ENOMEM;
+
+ dom_info->id = domain;
+ dom_info->cpli[0].id = CPL0;
+
+ return scmi_powercap_domain_attributes_get(ph, pinfo, dom_info);
+}
+
static int scmi_powercap_num_domains_get(const struct scmi_protocol_handle *ph)
{
struct powercap_info *pi = ph->get_priv(ph);
@@ -335,10 +359,11 @@ static int scmi_powercap_xfer_cap_get(const struct scmi_protocol_handle *ph,
static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_info *dom,
- u32 *power_cap)
+ u32 cpl_id, u32 *power_cap)
{
- if (dom->fc_info && dom->fc_info[POWERCAP_FC_CAP].get_addr) {
- *power_cap = ioread32(dom->fc_info[POWERCAP_FC_CAP].get_addr);
+ if (dom->cpli[cpl_id].fc_info &&
+ dom->cpli[cpl_id].fc_info[POWERCAP_FC_CAP].get_addr) {
+ *power_cap = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_CAP].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_CAP_GET,
dom->id, *power_cap, 0);
return 0;
@@ -348,7 +373,7 @@ static int __scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
}
static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 *power_cap)
+ u32 domain_id, u32 cpl_id, u32 *power_cap)
{
const struct scmi_powercap_info *dom;
@@ -359,12 +384,13 @@ static int scmi_powercap_cap_get(const struct scmi_protocol_handle *ph,
if (!dom)
return -EINVAL;
- return __scmi_powercap_cap_get(ph, dom, power_cap);
+ return __scmi_powercap_cap_get(ph, dom, cpl_id, power_cap);
}
static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
const struct scmi_powercap_info *pc,
- u32 power_cap, bool ignore_dresp)
+ u32 cpl_id, u32 power_cap,
+ bool ignore_dresp)
{
int ret;
struct scmi_xfer *t;
@@ -406,21 +432,23 @@ static int scmi_powercap_xfer_cap_set(const struct scmi_protocol_handle *ph,
static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
struct powercap_info *pi, u32 domain_id,
- u32 power_cap, bool ignore_dresp)
+ u32 cpl_id, u32 power_cap, bool ignore_dresp)
{
int ret = -EINVAL;
const struct scmi_powercap_info *pc;
pc = scmi_powercap_dom_info_get(ph, domain_id);
- if (!pc || !pc->powercap_cap_config)
+ if (!pc || !pc->cpli[cpl_id].cap_config)
return ret;
if (power_cap &&
- (power_cap < pc->min_power_cap || power_cap > pc->max_power_cap))
+ (power_cap < pc->cpli[cpl_id].min_power_cap ||
+ power_cap > pc->cpli[cpl_id].max_power_cap))
return ret;
- if (pc->fc_info && pc->fc_info[POWERCAP_FC_CAP].set_addr) {
- struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_CAP];
+ if (pc->cpli[cpl_id].fc_info &&
+ pc->cpli[cpl_id].fc_info[POWERCAP_FC_CAP].set_addr) {
+ struct scmi_fc_info *fci = &pc->cpli[cpl_id].fc_info[POWERCAP_FC_CAP];
iowrite32(power_cap, fci->set_addr);
ph->hops->fastchannel_db_ring(fci->set_db);
@@ -428,7 +456,7 @@ static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
domain_id, power_cap, 0);
ret = 0;
} else {
- ret = scmi_powercap_xfer_cap_set(ph, pc, power_cap,
+ ret = scmi_powercap_xfer_cap_set(ph, pc, cpl_id, power_cap,
ignore_dresp);
}
@@ -440,7 +468,7 @@ static int __scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
}
static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 power_cap,
+ u32 domain_id, u32 cpl_id, u32 power_cap,
bool ignore_dresp)
{
struct powercap_info *pi = ph->get_priv(ph);
@@ -459,7 +487,7 @@ static int scmi_powercap_cap_set(const struct scmi_protocol_handle *ph,
return 0;
}
- return __scmi_powercap_cap_set(ph, pi, domain_id,
+ return __scmi_powercap_cap_set(ph, pi, domain_id, cpl_id,
power_cap, ignore_dresp);
}
@@ -485,7 +513,7 @@ static int scmi_powercap_xfer_pai_get(const struct scmi_protocol_handle *ph,
}
static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 *pai)
+ u32 domain_id, u32 cpl_id, u32 *pai)
{
struct scmi_powercap_info *dom;
struct powercap_info *pi = ph->get_priv(ph);
@@ -494,8 +522,11 @@ static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
return -EINVAL;
dom = pi->powercaps + domain_id;
- if (dom->fc_info && dom->fc_info[POWERCAP_FC_PAI].get_addr) {
- *pai = ioread32(dom->fc_info[POWERCAP_FC_PAI].get_addr);
+ if (cpl_id >= dom->num_cpli)
+ return -EINVAL;
+
+ if (dom->cpli[cpl_id].fc_info && dom->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].get_addr) {
+ *pai = ioread32(dom->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].get_addr);
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_GET,
domain_id, *pai, 0);
return 0;
@@ -504,6 +535,12 @@ static int scmi_powercap_pai_get(const struct scmi_protocol_handle *ph,
return scmi_powercap_xfer_pai_get(ph, domain_id, pai);
}
+static int scmi_powercap_avg_interval_get(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *val)
+{
+ return scmi_powercap_pai_get(ph, domain_id, cpl_id, val);
+}
+
static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
u32 domain_id, u32 pai)
{
@@ -528,17 +565,18 @@ static int scmi_powercap_xfer_pai_set(const struct scmi_protocol_handle *ph,
}
static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
- u32 domain_id, u32 pai)
+ u32 domain_id, u32 cpl_id, u32 pai)
{
const struct scmi_powercap_info *pc;
pc = scmi_powercap_dom_info_get(ph, domain_id);
- if (!pc || !pc->powercap_pai_config || !pai ||
- pai < pc->min_pai || pai > pc->max_pai)
+ if (!pc || cpl_id >= pc->num_cpli || !pc->cpli[cpl_id].avg_ivl_config ||
+ !pai || pai < pc->cpli[cpl_id].min_avg_ivl ||
+ pai > pc->cpli[cpl_id].max_avg_ivl)
return -EINVAL;
- if (pc->fc_info && pc->fc_info[POWERCAP_FC_PAI].set_addr) {
- struct scmi_fc_info *fci = &pc->fc_info[POWERCAP_FC_PAI];
+ if (pc->cpli[cpl_id].fc_info && pc->cpli[cpl_id].fc_info[POWERCAP_FC_PAI].set_addr) {
+ struct scmi_fc_info *fci = &pc->cpli[cpl_id].fc_info[POWERCAP_FC_PAI];
trace_scmi_fc_call(SCMI_PROTOCOL_POWERCAP, POWERCAP_PAI_SET,
domain_id, pai, 0);
@@ -550,6 +588,12 @@ static int scmi_powercap_pai_set(const struct scmi_protocol_handle *ph,
return scmi_powercap_xfer_pai_set(ph, domain_id, pai);
}
+static int scmi_powercap_avg_interval_set(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 val)
+{
+ return scmi_powercap_pai_set(ph, domain_id, cpl_id, val);
+}
+
static int scmi_powercap_measurements_get(const struct scmi_protocol_handle *ph,
u32 domain_id, u32 *average_power,
u32 *pai)
@@ -645,11 +689,11 @@ static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
if (!pi->states[domain_id].last_pcap)
return -EINVAL;
- ret = __scmi_powercap_cap_set(ph, pi, domain_id,
+ ret = __scmi_powercap_cap_set(ph, pi, domain_id, CPL0,
pi->states[domain_id].last_pcap,
true);
} else {
- ret = __scmi_powercap_cap_set(ph, pi, domain_id, 0, true);
+ ret = __scmi_powercap_cap_set(ph, pi, domain_id, CPL0, 0, true);
}
if (ret)
@@ -660,7 +704,7 @@ static int scmi_powercap_cap_enable_set(const struct scmi_protocol_handle *ph,
* server could have ignored a disable request and kept enforcing some
* powercap limit requested by other agents.
*/
- ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
+ ret = scmi_powercap_cap_get(ph, domain_id, CPL0, &power_cap);
if (!ret)
pi->states[domain_id].enabled = !!power_cap;
@@ -682,7 +726,7 @@ static int scmi_powercap_cap_enable_get(const struct scmi_protocol_handle *ph,
* Report always real platform state; platform could have ignored
* a previous disable request. Default true on any error.
*/
- ret = scmi_powercap_cap_get(ph, domain_id, &power_cap);
+ ret = scmi_powercap_cap_get(ph, domain_id, CPL0, &power_cap);
if (!ret)
*enable = !!power_cap;
@@ -699,8 +743,8 @@ static const struct scmi_powercap_proto_ops powercap_proto_ops = {
.cap_set = scmi_powercap_cap_set,
.cap_enable_set = scmi_powercap_cap_enable_set,
.cap_enable_get = scmi_powercap_cap_enable_get,
- .pai_get = scmi_powercap_pai_get,
- .pai_set = scmi_powercap_pai_set,
+ .avg_interval_get = scmi_powercap_avg_interval_get,
+ .avg_interval_set = scmi_powercap_avg_interval_set,
.measurements_get = scmi_powercap_measurements_get,
.measurements_threshold_set = scmi_powercap_measurements_threshold_set,
.measurements_threshold_get = scmi_powercap_measurements_threshold_get,
@@ -991,18 +1035,18 @@ scmi_powercap_protocol_init(const struct scmi_protocol_handle *ph)
* formed and correlated by sane parent-child relationship (if any).
*/
for (domain = 0; domain < pinfo->num_domains; domain++) {
- ret = scmi_powercap_domain_attributes_get(ph, pinfo, domain);
+ ret = scmi_powercap_domain_initialize(ph, pinfo, domain);
if (ret)
return ret;
if (pinfo->powercaps[domain].fastchannels)
scmi_powercap_domain_init_fc(ph, domain,
- &pinfo->powercaps[domain].fc_info);
+ &pinfo->powercaps[domain].cpli[CPL0].fc_info);
/* Grab initial state when disable is supported. */
if (PROTOCOL_REV_MAJOR(ph->version) >= 0x2) {
ret = __scmi_powercap_cap_get(ph,
- &pinfo->powercaps[domain],
+ &pinfo->powercaps[domain], CPL0,
&pinfo->states[domain].last_pcap);
if (ret)
return ret;
diff --git a/drivers/powercap/arm_scmi_powercap.c b/drivers/powercap/arm_scmi_powercap.c
index ab66e9a3b1e2..be3007206a74 100644
--- a/drivers/powercap/arm_scmi_powercap.c
+++ b/drivers/powercap/arm_scmi_powercap.c
@@ -97,7 +97,7 @@ static const struct powercap_zone_ops zone_ops = {
};
static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz,
- u64 power_limit_uw, u32 *norm)
+ u64 power_limit_uw, int cid, u32 *norm)
{
bool scale_mw = spz->info->powercap_scale_mw;
u64 val;
@@ -108,9 +108,9 @@ static void scmi_powercap_normalize_cap(const struct scmi_powercap_zone *spz,
* the range [min_power_cap, max_power_cap] whose bounds are assured to
* be two unsigned 32bits quantities.
*/
- *norm = clamp_t(u32, val, spz->info->min_power_cap,
- spz->info->max_power_cap);
- *norm = rounddown(*norm, spz->info->power_cap_step);
+ *norm = clamp_t(u32, val, spz->info->cpli[cid].min_power_cap,
+ spz->info->cpli[cid].max_power_cap);
+ *norm = rounddown(*norm, spz->info->cpli[cid].power_cap_step);
val = (scale_mw) ? *norm * 1000 : *norm;
if (power_limit_uw != val)
@@ -125,12 +125,12 @@ static int scmi_powercap_set_power_limit_uw(struct powercap_zone *pz, int cid,
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
u32 norm_power;
- if (!spz->info->powercap_cap_config)
+ if (!spz->info->cpli[cid].cap_config)
return -EINVAL;
- scmi_powercap_normalize_cap(spz, power_uw, &norm_power);
+ scmi_powercap_normalize_cap(spz, power_uw, cid, &norm_power);
- return powercap_ops->cap_set(spz->ph, spz->info->id, norm_power, false);
+ return powercap_ops->cap_set(spz->ph, spz->info->id, cid, norm_power, false);
}
static int scmi_powercap_get_power_limit_uw(struct powercap_zone *pz, int cid,
@@ -140,7 +140,7 @@ static int scmi_powercap_get_power_limit_uw(struct powercap_zone *pz, int cid,
u32 power;
int ret;
- ret = powercap_ops->cap_get(spz->ph, spz->info->id, &power);
+ ret = powercap_ops->cap_get(spz->ph, spz->info->id, cid, &power);
if (ret)
return ret;
@@ -152,19 +152,20 @@ static int scmi_powercap_get_power_limit_uw(struct powercap_zone *pz, int cid,
}
static void scmi_powercap_normalize_time(const struct scmi_powercap_zone *spz,
- u64 time_us, u32 *norm)
+ u64 time_us, int cid, u32 *norm)
{
/*
* This cast is lossless since here @time_us is certain to be within the
- * range [min_pai, max_pai] whose bounds are assured to be two unsigned
- * 32bits quantities.
+ * range [min_avg_ivl, max_avg_ivl] whose bounds are assured to be two
+ * unsigned 32bits quantities.
*/
- *norm = clamp_t(u32, time_us, spz->info->min_pai, spz->info->max_pai);
- *norm = rounddown(*norm, spz->info->pai_step);
+ *norm = clamp_t(u32, time_us, spz->info->cpli[cid].min_avg_ivl,
+ spz->info->cpli[cid].max_avg_ivl);
+ *norm = rounddown(*norm, spz->info->cpli[cid].avg_ivl_step);
if (time_us != *norm)
dev_dbg(spz->dev,
- "Normalized %s:PAI - requested:%llu - normalized:%u\n",
+ "Normalized %s:AVG_IVL - requested:%llu - normalized:%u\n",
spz->info->name, time_us, *norm);
}
@@ -174,12 +175,13 @@ static int scmi_powercap_set_time_window_us(struct powercap_zone *pz, int cid,
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
u32 norm_pai;
- if (!spz->info->powercap_pai_config)
+ if (!spz->info->cpli[cid].avg_ivl_config)
return -EINVAL;
- scmi_powercap_normalize_time(spz, time_window_us, &norm_pai);
+ scmi_powercap_normalize_time(spz, time_window_us, cid, &norm_pai);
- return powercap_ops->pai_set(spz->ph, spz->info->id, norm_pai);
+ return powercap_ops->avg_interval_set(spz->ph, spz->info->id,
+ cid, norm_pai);
}
static int scmi_powercap_get_time_window_us(struct powercap_zone *pz, int cid,
@@ -189,7 +191,7 @@ static int scmi_powercap_get_time_window_us(struct powercap_zone *pz, int cid,
int ret;
u32 pai;
- ret = powercap_ops->pai_get(spz->ph, spz->info->id, &pai);
+ ret = powercap_ops->avg_interval_get(spz->ph, spz->info->id, cid, &pai);
if (ret)
return ret;
@@ -203,7 +205,7 @@ static int scmi_powercap_get_max_power_uw(struct powercap_zone *pz, int cid,
{
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
- *max_power_uw = spz->info->max_power_cap;
+ *max_power_uw = spz->info->cpli[cid].max_power_cap;
if (spz->info->powercap_scale_mw)
*max_power_uw *= 1000;
@@ -215,7 +217,7 @@ static int scmi_powercap_get_min_power_uw(struct powercap_zone *pz, int cid,
{
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
- *min_power_uw = spz->info->min_power_cap;
+ *min_power_uw = spz->info->cpli[cid].min_power_cap;
if (spz->info->powercap_scale_mw)
*min_power_uw *= 1000;
@@ -227,7 +229,7 @@ static int scmi_powercap_get_max_time_window_us(struct powercap_zone *pz,
{
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
- *time_window_us = spz->info->max_pai;
+ *time_window_us = spz->info->cpli[cid].max_avg_ivl;
return 0;
}
@@ -237,14 +239,16 @@ static int scmi_powercap_get_min_time_window_us(struct powercap_zone *pz,
{
struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
- *time_window_us = (u64)spz->info->min_pai;
+ *time_window_us = (u64)spz->info->cpli[cid].min_avg_ivl;
return 0;
}
static const char *scmi_powercap_get_name(struct powercap_zone *pz, int cid)
{
- return "SCMI power-cap";
+ struct scmi_powercap_zone *spz = to_scmi_powercap_zone(pz);
+
+ return spz->info->cpli[cid].name;
}
static const struct powercap_zone_constraint_ops constraint_ops = {
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index aafaac1496b0..9918fb30100c 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -2,7 +2,7 @@
/*
* SCMI Message Protocol driver header
*
- * Copyright (C) 2018-2021 ARM Ltd.
+ * Copyright (C) 2018-2026 ARM Ltd.
*/
#ifndef _LINUX_SCMI_PROTOCOL_H
@@ -609,6 +609,35 @@ struct scmi_voltage_proto_ops {
s32 *volt_uV);
};
+/**
+ * struct scmi_powercap_cpl_info - Describe one CPL - Concurrent Powercap Limit
+ *
+ * @id: CPL ID as advertised by the platform.
+ * @cap_config: CAP configuration support for this CPL.
+ * @min_power_cap: Minimum configurable CAP.
+ * @max_power_cap: Maximum configurable CAP.
+ * @power_cap_step: Step size between two consecutive CAP values.
+ * @avg_ivl_config: Powercap averaging interval configuration support.
+ * @min_avg_ivl: Minimum configurable powercap averaging interval.
+ * @max_avg_ivl: Maximum configurable powercap averaging interval.
+ * @avg_ivl_step: Step size between two consecutive averaging intervals.
+ * @name: name assigned to the Powercap Domain by platform.
+ * @fc_info: Reference to the FastChannels descriptors supported by this CPL
+ */
+struct scmi_powercap_cpl_info {
+ unsigned int id;
+ bool cap_config;
+ unsigned int min_power_cap;
+ unsigned int max_power_cap;
+ unsigned int power_cap_step;
+ bool avg_ivl_config;
+ unsigned int min_avg_ivl;
+ unsigned int max_avg_ivl;
+ unsigned int avg_ivl_step;
+ char name[SCMI_SHORT_NAME_MAX_SIZE];
+ struct scmi_fc_info *fc_info;
+};
+
/**
* struct scmi_powercap_info - Describe one available Powercap domain
*
@@ -617,21 +646,15 @@ struct scmi_voltage_proto_ops {
* @notify_powercap_measurement_change: MEASUREMENTS change notifications
* support.
* @async_powercap_cap_set: Asynchronous CAP set support.
- * @powercap_cap_config: CAP configuration support.
* @powercap_monitoring: Monitoring (measurements) support.
- * @powercap_pai_config: PAI configuration support.
* @powercap_scale_mw: Domain reports power data in milliwatt units.
* @powercap_scale_uw: Domain reports power data in microwatt units.
* Note that, when both @powercap_scale_mw and
* @powercap_scale_uw are set to false, the domain
* reports power data on an abstract linear scale.
+ * @extended_names: Support for long names.
+ * @fastchannels: Support for at least one fastchannel,
* @name: name assigned to the Powercap Domain by platform.
- * @min_pai: Minimum configurable PAI.
- * @max_pai: Maximum configurable PAI.
- * @pai_step: Step size between two consecutive PAI values.
- * @min_power_cap: Minimum configurable CAP.
- * @max_power_cap: Maximum configurable CAP.
- * @power_cap_step: Step size between two consecutive CAP values.
* @sustainable_power: Maximum sustainable power consumption for this domain
* under normal conditions.
* @accuracy: The accuracy with which the power is measured and reported in
@@ -639,30 +662,25 @@ struct scmi_voltage_proto_ops {
* @parent_id: Identifier of the containing parent power capping domain, or the
* value 0xFFFFFFFF if this powercap domain is a root domain not
* contained in any other domain.
+ * @num_cpli: Number of discovered CPLs.
+ * @cpli: Reference to an array holding descriptors to all the discovered CPLs.
*/
struct scmi_powercap_info {
unsigned int id;
bool notify_powercap_cap_change;
bool notify_powercap_measurement_change;
bool async_powercap_cap_set;
- bool powercap_cap_config;
bool powercap_monitoring;
- bool powercap_pai_config;
bool powercap_scale_mw;
bool powercap_scale_uw;
bool fastchannels;
char name[SCMI_MAX_STR_SIZE];
- unsigned int min_pai;
- unsigned int max_pai;
- unsigned int pai_step;
- unsigned int min_power_cap;
- unsigned int max_power_cap;
- unsigned int power_cap_step;
unsigned int sustainable_power;
unsigned int accuracy;
#define SCMI_POWERCAP_ROOT_ZONE_ID 0xFFFFFFFFUL
unsigned int parent_id;
- struct scmi_fc_info *fc_info;
+ unsigned int num_cpli;
+ struct scmi_powercap_cpl_info *cpli;
};
/**
@@ -691,8 +709,12 @@ struct scmi_powercap_info {
* on the system: for this reason @cap_get and @cap_enable_get
* will always report the final platform view of the powercaps.
* @cap_enable_get: get the current CAP enable status for the specified domain.
- * @pai_get: get the current PAI value for the specified domain.
- * @pai_set: set the PAI value for the specified domain to the provided value.
+ * @avg_interval_get: get the current averaging interval value for the specified
+ * domain. This will get the PAI or CAI depending on the used
+ * protocol version.
+ * @avg_interval_set: set the current averaging interval value for the specified
+ * domain. This will set the PAI or CAI depending on the used
+ * protocol version.
* @measurements_get: retrieve the current average power measurements for the
* specified domain and the related PAI upon which is
* calculated.
@@ -716,17 +738,17 @@ struct scmi_powercap_proto_ops {
const struct scmi_powercap_info __must_check *(*info_get)
(const struct scmi_protocol_handle *ph, u32 domain_id);
int (*cap_get)(const struct scmi_protocol_handle *ph, u32 domain_id,
- u32 *power_cap);
+ u32 cpl_id, u32 *power_cap);
int (*cap_set)(const struct scmi_protocol_handle *ph, u32 domain_id,
- u32 power_cap, bool ignore_dresp);
+ u32 cpl_id, u32 power_cap, bool ignore_dresp);
int (*cap_enable_set)(const struct scmi_protocol_handle *ph,
u32 domain_id, bool enable);
int (*cap_enable_get)(const struct scmi_protocol_handle *ph,
u32 domain_id, bool *enable);
- int (*pai_get)(const struct scmi_protocol_handle *ph, u32 domain_id,
- u32 *pai);
- int (*pai_set)(const struct scmi_protocol_handle *ph, u32 domain_id,
- u32 pai);
+ int (*avg_interval_get)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 *val);
+ int (*avg_interval_set)(const struct scmi_protocol_handle *ph,
+ u32 domain_id, u32 cpl_id, u32 val);
int (*measurements_get)(const struct scmi_protocol_handle *ph,
u32 domain_id, u32 *average_power, u32 *pai);
int (*measurements_threshold_set)(const struct scmi_protocol_handle *ph,
--
2.47.3
^ permalink raw reply related
* [PATCH v6 01/12] firmware: arm_scmi: Add an optional custom parameter to fastchannel helpers
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Cristian Marussi,
Philip Radford
In-Reply-To: <20260518135234.2953532-1-philip.radford@arm.com>
From: Cristian Marussi <cristian.marussi@arm.com>
Starting from SCMIv4.0 the protocols DESCRIBE_FASTCHANNEL commands allow
to specify one additional per-protocol custom field in the outgoing message
request in order to, optionally, further narrow down the scope of the
fastchannel discovery request; the related message-reply format is instead
unchanged.
Add an optional custom protocol parameter to the common fastchannel helper
so as to enable the caller to choose the kind of message to send based on
the detected protocol version.
Signed-off-by: Cristian Marussi <cristian.marussi@arm.com>
Signed-off-by: Philip Radford <philip.radford@arm.com>
---
drivers/firmware/arm_scmi/driver.c | 12 ++++++++++--
drivers/firmware/arm_scmi/perf.c | 8 ++++----
drivers/firmware/arm_scmi/powercap.c | 8 ++++----
drivers/firmware/arm_scmi/protocols.h | 2 +-
4 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index f247e19cff87..53ae4cfa10b1 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -1872,6 +1872,11 @@ static int scmi_iterator_run(void *iter)
struct scmi_msg_get_fc_info {
__le32 domain;
__le32 message_id;
+ __le32 custom;
+#define MSG_FC_INFO_SZ_EXTENDED \
+ (sizeof(struct scmi_msg_get_fc_info))
+#define MSG_FC_INFO_SZ \
+ (sizeof(struct scmi_msg_get_fc_info) - sizeof(__le32))
};
struct scmi_msg_resp_desc_fc {
@@ -1900,7 +1905,7 @@ struct scmi_msg_resp_desc_fc {
static void
scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
u8 describe_id, u32 message_id, u32 valid_size,
- u32 domain, void __iomem **p_addr,
+ u32 domain, u32 *custom, void __iomem **p_addr,
struct scmi_fc_db_info **p_db, u32 *rate_limit)
{
int ret;
@@ -1931,13 +1936,16 @@ scmi_common_fastchannel_init(const struct scmi_protocol_handle *ph,
}
ret = ph->xops->xfer_get_init(ph, describe_id,
- sizeof(*info), sizeof(*resp), &t);
+ custom ? MSG_FC_INFO_SZ_EXTENDED :
+ MSG_FC_INFO_SZ, sizeof(*resp), &t);
if (ret)
goto err_out;
info = t->tx.buf;
info->domain = cpu_to_le32(domain);
info->message_id = cpu_to_le32(message_id);
+ if (custom)
+ info->custom = cpu_to_le32(*custom);
/*
* Bail out on error leaving fc_info addresses zeroed; this includes
diff --git a/drivers/firmware/arm_scmi/perf.c b/drivers/firmware/arm_scmi/perf.c
index 4583d02bee1c..7f283f457e02 100644
--- a/drivers/firmware/arm_scmi/perf.c
+++ b/drivers/firmware/arm_scmi/perf.c
@@ -835,25 +835,25 @@ static void scmi_perf_domain_init_fc(const struct scmi_protocol_handle *ph,
return;
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
- PERF_LEVEL_GET, 4, dom->id,
+ PERF_LEVEL_GET, 4, dom->id, NULL,
&fc[PERF_FC_LEVEL].get_addr, NULL,
&fc[PERF_FC_LEVEL].rate_limit);
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
- PERF_LIMITS_GET, 8, dom->id,
+ PERF_LIMITS_GET, 8, dom->id, NULL,
&fc[PERF_FC_LIMIT].get_addr, NULL,
&fc[PERF_FC_LIMIT].rate_limit);
if (dom->info.set_perf)
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
- PERF_LEVEL_SET, 4, dom->id,
+ PERF_LEVEL_SET, 4, dom->id, NULL,
&fc[PERF_FC_LEVEL].set_addr,
&fc[PERF_FC_LEVEL].set_db,
&fc[PERF_FC_LEVEL].rate_limit);
if (dom->set_limits)
ph->hops->fastchannel_init(ph, PERF_DESCRIBE_FASTCHANNEL,
- PERF_LIMITS_SET, 8, dom->id,
+ PERF_LIMITS_SET, 8, dom->id, NULL,
&fc[PERF_FC_LIMIT].set_addr,
&fc[PERF_FC_LIMIT].set_db,
&fc[PERF_FC_LIMIT].rate_limit);
diff --git a/drivers/firmware/arm_scmi/powercap.c b/drivers/firmware/arm_scmi/powercap.c
index ab9733f4458b..22aff71c75e9 100644
--- a/drivers/firmware/arm_scmi/powercap.c
+++ b/drivers/firmware/arm_scmi/powercap.c
@@ -716,24 +716,24 @@ static void scmi_powercap_domain_init_fc(const struct scmi_protocol_handle *ph,
return;
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_CAP_SET, 4, domain,
+ POWERCAP_CAP_SET, 4, domain, NULL,
&fc[POWERCAP_FC_CAP].set_addr,
&fc[POWERCAP_FC_CAP].set_db,
&fc[POWERCAP_FC_CAP].rate_limit);
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_CAP_GET, 4, domain,
+ POWERCAP_CAP_GET, 4, domain, NULL,
&fc[POWERCAP_FC_CAP].get_addr, NULL,
&fc[POWERCAP_FC_CAP].rate_limit);
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_PAI_SET, 4, domain,
+ POWERCAP_PAI_SET, 4, domain, NULL,
&fc[POWERCAP_FC_PAI].set_addr,
&fc[POWERCAP_FC_PAI].set_db,
&fc[POWERCAP_FC_PAI].rate_limit);
ph->hops->fastchannel_init(ph, POWERCAP_DESCRIBE_FASTCHANNEL,
- POWERCAP_PAI_GET, 4, domain,
+ POWERCAP_PAI_GET, 4, domain, NULL,
&fc[POWERCAP_FC_PAI].get_addr, NULL,
&fc[POWERCAP_FC_PAI].rate_limit);
diff --git a/drivers/firmware/arm_scmi/protocols.h b/drivers/firmware/arm_scmi/protocols.h
index f51245aca259..e618d3141c95 100644
--- a/drivers/firmware/arm_scmi/protocols.h
+++ b/drivers/firmware/arm_scmi/protocols.h
@@ -280,7 +280,7 @@ struct scmi_proto_helpers_ops {
u32 message_id, u32 *attributes);
void (*fastchannel_init)(const struct scmi_protocol_handle *ph,
u8 describe_id, u32 message_id,
- u32 valid_size, u32 domain,
+ u32 valid_size, u32 domain, u32 *custom,
void __iomem **p_addr,
struct scmi_fc_db_info **p_db,
u32 *rate_limit);
--
2.47.3
^ permalink raw reply related
* [PATCH v6 00/12] Add support for SCMIv4.0 Powercap Extensions
From: Philip Radford @ 2026-05-18 13:52 UTC (permalink / raw)
To: linux-kernel, linux-arm-kernel, arm-scmi, linux-pm
Cc: sudeep.holla, james.quinlan, f.fainelli, vincent.guittot,
etienne.carriere, peng.fan, michal.simek, quic_sibis,
dan.carpenter, d-gole, souvik.chakravarty, Philip Radford
Hi all,
I will be taking over this series from Cristian and in doing so I have
addressed a couple of issues raised by the first version and added five
additional patches since Cristian's original series:
[6/12] exposes the measurement averaging interval (MAI) value when the
agent has registered to receive power measurement change notifications
for the power capping domain.
[9/12] adds MAI get and set support for the powercap protocol.
[10/12] introduces a synthetic root zone to act as a common parent for all
top-level domains.
[11/12] adds get_power_uw to synthetic root zone, summing the per-zone
power of immediate child zones.
[12/12] adds enable/disable functionality to synthetic root zone to
enable/disable immediate children.
The original series was based on v6.17-rc1 whereas this version has been
based on v7.1-rc1.
The rest of Cristian's series is explained below;
SCMIv4.0 [1] introduces some new features and commands into the Powercap
protocol. In a nutshell, such protocol changes add support for:
- setting multiple powercap limit/interval constraints for each SCMI
powercap domain which supports multiple Concurrent Power Limit
- enabling more Powercap commands to use Fastchannels mechanism
- adding multiple constraints support to the existing notifications
After a bit of needed updates in the SCMI core this series adds:
- support for the idea of optional multiple Concurrent Power Limit (CPLs)
- support for the new FCs
- support for extended notifications
- enable usage of such multiple constraint in the ARM SCMI Powercap driver
Note that the public SCMIv4.0 spec at [1] is currently still BETA0, so
this series could anyway need some minor rework along the way and
definitely will need to wait for a final public release before being
possibly merged.
Tested on a single and multi-instance scenario on an emulated setup
implementing the new protocol extensions.
Based on v7.1-rc1.
Thanks,
Phil
---
V5->V6
- Re-worded existing comment for POWERCAP_MEASUREMENTS_NOTIFY
- Added define for V2/V3 payload sizes
- Used new definitions for payload sizes
- Fixed comment length
- Changed warning message warning
- Fixed line lengths and alignment
- Updated docs for new fields
- Amended omission of spz initialization when unregistering powercap zones
- Tested unloading and loading powercap module
- Re-wrote commit message
- Added use of to_scmi_powercap_root macro
- Changed instance_root_set_enable_state to bail out on any error
V4->V5
- Added enable/disable functionality to synthetic node
- Rebased on v7.1-rc1
V3->V4
- Rebased on v7.0-rc4
- Added sythentic parent node and functionality
- Moved fastchannel inits outside of loop
- Renamed arguments for consistency
V2->V3
- Added powercap MAI get/set support
V1->V2
- Rebased on sudeep/for-next/scmi/updates
- Amended Copyright to include 2026
- Added patch to extend powercap report to include MAI
- Removed creation of pi powercap_info struct due to legacy code change
- Amended references to pi->version and similar, which were based on
legacy code
- Wrapped two variables in le32_to_cpu() to appease Sparse warnings
- Amended comparing operator value in response to feedback
Cristian Marussi (7):
firmware: arm_scmi: Add an optional custom parameter to fastchannel
helpers
firmware: arm_scmi: Refactor powercap domain layout
firmware: arm_scmi: Add SCMIv4.0 Powercap basic support
firmware: arm_scmi: Add SCMIv4.0 Powercap FCs support
firmware: arm_scmi: Add SCMIV4.0 Powercap notifications support
include: trace: Add new parameter to trace_scmi_fc_call
powercap: arm_scmi: Enable multiple constraints support
Philip Radford (5):
firmware: arm_scmi: Extend powercap report to include MAI
firmware: arm_scmi: add Powercap MAI get/set support
powercap: arm_scmi: Create synthetic parent node for multi-instance
powercap: arm_scmi: Add get_power_uw to synthetic node
powercap: arm_scmi: Synthetic zone enable/disable
drivers/firmware/arm_scmi/driver.c | 12 +-
drivers/firmware/arm_scmi/perf.c | 16 +-
drivers/firmware/arm_scmi/powercap.c | 999 ++++++++++++++++++++------
drivers/firmware/arm_scmi/protocols.h | 2 +-
drivers/powercap/arm_scmi_powercap.c | 291 +++++++-
include/linux/scmi_protocol.h | 97 ++-
include/trace/events/scmi.h | 12 +-
7 files changed, 1150 insertions(+), 279 deletions(-)
--
2.47.3
^ permalink raw reply
* Re: [PATCH v2 0/6] fsl-mc: Move over to device MSI infrastructure
From: Christophe Leroy (CS GROUP) @ 2026-05-18 13:51 UTC (permalink / raw)
To: Marc Zyngier, Arnd Bergmann
Cc: Ioana Ciornei, Thomas Gleixner, Sascha Bischoff, linux-kernel,
linux-arm-kernel, linuxppc-dev
In-Reply-To: <87v7cva080.wl-maz@kernel.org>
Hi Marc,
Le 10/05/2026 à 15:00, Marc Zyngier a écrit :
> On Thu, 26 Feb 2026 09:50:43 +0000,
> "Christophe Leroy (CS GROUP)" <chleroy@kernel.org> wrote:
>>
>>
>> On Tue, 24 Feb 2026 10:09:30 +0000, Marc Zyngier wrote:
>>> This is the second drop of this cleanup series for the fsl-mc MSI
>>> infrastructure, initially posted at [1].
>>>
>>> * From v1 [1]:
>>>
>>> - Drop the now unused DOMAIN_BUS_FSL_MC_MSI bus token
>>>
>>> [...]
>>
>> Applied, thanks!
>>
>> [1/6] fsl-mc: Remove MSI domain propagation to sub-devices
>> commit: 1fb7392ee3408494d4d62c09a8c3e5f5934caba7
>> [2/6] fsl-mc: Add minimal infrastructure to use platform MSI
>> commit: 0c9f522f2d41c7e055a602a0d2c41dc7af01010b
>> [3/6] irqchip/gic-v3-its: Add fsl_mc device plumbing to the msi-parent handling
>> commit: cf3179b4e53f527aba9f0c6c3b921619c8adf761
>> [4/6] fsl-mc: Switch over to per-device platform MSI
>> commit: 4a958e47c246fa3fb8954f4303e0da15ab3d026d
>> [5/6] fsl-mc: Remove legacy MSI implementation
>> commit: 14b1cbcc6cec0b02298f4adf717646cd943b7ef6
>> [6/6] platform-msi: Remove stale comment
>> commit: f0a2eac6a597268034fd40d92c1469182438b53d
>
> Is there any particular reason why this didn't make it into 7.1?
I sent a pull request [1] as early as possible after Easter break, but
it was apparently too late. Or maybe that was because I did a last
minute rebase, I'm not sure what the real reason. I tentatively sent an
alternative pull request [2] the day after after rolling back the
rebase, but I got no feedback.
>
> I was really looking forward to some additional cleanups in the GICv3
> ITS code, and this gets in the way.
It is still in linux-next and finger crossed will go in 7.2
> > Do I need to respin it?
No, I'd like to avoid having to rebase again. If you have changes to the
series please send followup patches.
Christophe
[1]
https://patchwork.kernel.org/project/linux-soc/patch/69cdadd6-523c-4a79-8cb3-1deff5910699@kernel.org/
[2]
https://patchwork.kernel.org/project/linux-soc/patch/310b65ba-1d73-4ce0-b332-00cde70acc69@kernel.org/
^ permalink raw reply
* Re: [RFC PATCH 1/2] KVM: arm64: Introduce S2 walker SKIP return options
From: Leonardo Bras @ 2026-05-18 13:45 UTC (permalink / raw)
To: Will Deacon
Cc: Leonardo Bras, Oliver Upton, Marc Zyngier, Joey Gouly,
Suzuki K Poulose, Zenghui Yu, Catalin Marinas, Fuad Tabba,
Raghavendra Rao Ananta, linux-arm-kernel, kvmarm, linux-kernel
In-Reply-To: <agrTQMw4QJX6HGrm@willie-the-truck>
Hello Oliver, Will,
Thanks for reviewing!
On Mon, May 18, 2026 at 09:52:16AM +0100, Will Deacon wrote:
> On Mon, May 18, 2026 at 12:22:47AM -0700, Oliver Upton wrote:
> > On Fri, May 15, 2026 at 08:59:02PM +0100, Leonardo Bras wrote:
> > > Introduce S2 walker return values:
> > > - SKIP_CHILDREN: skip walking the children of the current node
> > > - SKIP_SIBLINGS: skip waling the siblings of the current node
> > >
> > > Also, modify __kvm_pgtable_visit() to fulfil the hing on above return
> > > values. Current walkers should not be impacted
> >
> > I'd rather see something based around new walk flags than introducing an
> > entirely new mechanic around return values.
> >
> > e.g. you could split the LEAF flag into separate flags for blocks v.
> > pages:
> >
> > KVM_PGTABLE_WALK_PAGE,
> > KVM_PGTABLE_WALK_BLOCK,
> > KVM_PGTABLE_WALK_LEAF = KVM_PGTABLE_WALK_PAGE |
> > KVM_PGTABLE_WALK_BLOCK,
> >
> > and then let __kvm_pgtable_visit() decide how to steer the walk. You may
> > need some special handling to get the address arithmetic right when
> > skipping over a table of page descriptors.
I am probably not getting the whole inner workings of this solution, but
IIUC the idea would be to walk the blocks, but not the pages, right?
Blocks meaning level2- and pages being level3?
> I was wondering along similar lines, but maybe it would be useful just
> to pass a maximum level to the walker logic? That feels like the most
> general case without complicating the existing logic.
This proposal seems simpler for me to understand, and indeed looks like a
better solution than what I have proposed, taking care of the
'already split' case with better performance, as it don't even walk a
single level-3 entry.
On the 'splitting' case, it also works flawlessly if the memory is given in
level-2 blocks. There is only one case that I would like to address here:
- Memory given in level-1 blocks (say 1GB)
- Walker flag says 'walk down to level-2 only'
- Split Walker on level-1 will break page down to (up to) level-3 entries.
- Walker will continue to be called on level-2 entries, even though it's
not necessary.
To solve this, I would like to suggest a new flag, that skips a table
that has just been created. This could be easily implemented in
__kvm_page_visit() on top of the max level flags suggested.
enum kvm_pgtable_walk_flags {
[...]
KVM_PGTABLE_WALK_SKIP_LEVEL3 = BIT(7),
KVM_PGTABLE_WALK_SKIP_LEVEL2 = BIT(8),
KVM_PGTABLE_WALK_SKIP_LEVEL1 = BIT(9),
KVM_PGTABLE_WALK_SKIP_NEW_TABLE = BIT(10),
};
How does that sound?
Thanks!
Leo
^ permalink raw reply
* Re: [PATCH v3 0/2] arm_ffa, KVM: Fix FF-A emad offset calculations
From: Sudeep Holla @ 2026-05-18 13:45 UTC (permalink / raw)
To: Sebastian Ene
Cc: catalin.marinas, maz, oupton, Sudeep Holla, will, joey.gouly,
korneld, kvmarm, linux-arm-kernel, linux-kernel, android-kvm,
mrigendra.chaubey, perlarsen, suzuki.poulose, vdonnefort,
yuzenghui
In-Reply-To: <20260513-ludicrous-beautiful-cuttlefish-34271d@sudeepholla>
On Wed, May 13, 2026 at 06:23:43PM +0100, Sudeep Holla wrote:
> On Tue, May 12, 2026 at 12:44:40PM +0000, Sebastian Ene wrote:
> > Hi all,
> >
> > This series fixes the Endpoint Memory Access Descriptor (EMAD) offset calculations
> > and adds the necessary bounds checks for both the core FF-A driver and the pKVM
> > hypervisor.
> >
> > Prior to FF-A version 1.1, the memory region header didn't specify an explicit offset
> > for the EMADs, leading to the assumption that they immediately follow the header.
> > However, from v1.1 onwards, the specification dictates using the `ep_mem_offset` field
> > to determine the start of the memory access array.
> >
> > The patches in this series address this by:
> > 1. Updating the core `arm_ffa` firmware driver to correctly calculate the descriptor
> > offset using `ep_mem_offset` rather than defaulting to `sizeof(struct ffa_mem_region)`.
> > It also introduces bounds checking against `max_fragsize`.
> > 2. Enhancing the pKVM hypervisor validation logic to no longer strictly enforce that
> > the descriptor strictly follows the header, aligning it with the driver behavior
> > and the FF-A specification, while also ensuring the offset falls within the mailbox
> > buffer bounds.
> >
>
> Looks good apart from the minor nits, but how do you plan to route these
> changes as they are dependent for functionality but not for the build IIUC.
>
You can add (with minor nit fixed) my
Reviewed-by: Sudeep Holla <sudeep.holla@kernel.org>
if it is routed via KVM or other tree.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH] drm/mediatek: Convert legacy DRM logging to drm_* helpers in mtk_dsi.c
From: Chun-Kuang Hu @ 2026-05-18 13:39 UTC (permalink / raw)
To: Abhishek Rajput
Cc: chunkuang.hu, p.zabel, airlied, simona, matthias.bgg,
angelogioacchino.delregno, dri-devel, linux-mediatek,
linux-kernel, linux-arm-kernel
In-Reply-To: <20260420052008.5417-1-abhiraj21put@gmail.com>
Hi, Abhishek:
Abhishek Rajput <abhiraj21put@gmail.com> 於 2026年4月20日週一 上午5:20寫道:
>
> Replace DRM_INFO(), DRM_WARN() and DRM_ERROR() calls in
> drivers/gpu/drm/mediatek/mtk_dsi.c with the corresponding
> drm_info(), drm_warn() and drm_err() helpers.
>
> The drm_*() logging helpers take a struct drm_device * argument,
> allowing the DRM core to prefix log messages with the correct device
> name and instance. This is required to correctly distinguish log
> messages on systems with multiple GPUs.
>
> This change aligns the radeon driver with the DRM TODO item:
> "Convert logging to drm_* functions with drm_device parameter".
Applied to mediatek-drm-next [1], thanks.
[1] https://git.kernel.org/pub/scm/linux/kernel/git/chunkuang.hu/linux.git/log/?h=mediatek-drm-next
Regards,
Chun-Kuang.
>
> Signed-off-by: Abhishek Rajput <abhiraj21put@gmail.com>
>
> diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
> index 0e2bcd5f67b7..a67ad575f5f0 100644
> --- a/drivers/gpu/drm/mediatek/mtk_dsi.c
> +++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
> @@ -510,6 +510,7 @@ static void mtk_dsi_config_vdo_timing_per_line_lp(struct mtk_dsi *dsi)
> u32 delta;
> struct mtk_phy_timing *timing = &dsi->phy_timing;
> struct videomode *vm = &dsi->vm;
> + struct drm_device *drm = dsi->bridge.dev;
>
> if (dsi->format == MIPI_DSI_FMT_RGB565)
> dsi_tmp_buf_bpp = 2;
> @@ -543,7 +544,7 @@ static void mtk_dsi_config_vdo_timing_per_line_lp(struct mtk_dsi *dsi)
> horizontal_backporch_byte /
> horizontal_front_back_byte;
> } else {
> - DRM_WARN("HFP + HBP less than d-phy, FPS will under 60Hz\n");
> + drm_warn(drm, "HFP + HBP less than d-phy, FPS will under 60Hz\n");
> }
>
> if ((dsi->mode_flags & MIPI_DSI_HS_PKT_END_ALIGNED) &&
> @@ -623,12 +624,13 @@ static s32 mtk_dsi_wait_for_irq_done(struct mtk_dsi *dsi, u32 irq_flag,
> {
> s32 ret = 0;
> unsigned long jiffies = msecs_to_jiffies(timeout);
> + struct drm_device *drm = dsi->bridge.dev;
>
> ret = wait_event_interruptible_timeout(dsi->irq_wait_queue,
> dsi->irq_data & irq_flag,
> jiffies);
> if (ret == 0) {
> - DRM_WARN("Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
> + drm_warn(drm, "Wait DSI IRQ(0x%08x) Timeout\n", irq_flag);
>
> mtk_dsi_enable(dsi);
> mtk_dsi_reset_engine(dsi);
> @@ -663,9 +665,10 @@ static s32 mtk_dsi_switch_to_cmd_mode(struct mtk_dsi *dsi, u8 irq_flag, u32 t)
> {
> mtk_dsi_irq_data_clear(dsi, irq_flag);
> mtk_dsi_set_cmd_mode(dsi);
> + struct drm_device *drm = dsi->bridge.dev;
>
> if (!mtk_dsi_wait_for_irq_done(dsi, irq_flag, t)) {
> - DRM_ERROR("failed to switch cmd mode\n");
> + drm_err(drm, "failed to switch cmd mode\n");
> return -ETIME;
> } else {
> return 0;
> @@ -849,11 +852,12 @@ static void mtk_dsi_bridge_atomic_pre_enable(struct drm_bridge *bridge,
> struct drm_atomic_state *state)
> {
> struct mtk_dsi *dsi = bridge_to_dsi(bridge);
> + struct drm_device *drm = bridge->dev;
> int ret;
>
> ret = mtk_dsi_poweron(dsi);
> if (ret < 0)
> - DRM_ERROR("failed to power on dsi\n");
> + drm_err(drm, "failed to power on dsi\n");
> }
>
> static void mtk_dsi_bridge_atomic_post_disable(struct drm_bridge *bridge,
> @@ -916,7 +920,7 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
> ret = drm_simple_encoder_init(drm, &dsi->encoder,
> DRM_MODE_ENCODER_DSI);
> if (ret) {
> - DRM_ERROR("Failed to encoder init to drm\n");
> + drm_err(drm, "Failed to encoder init to drm\n");
> return ret;
> }
>
> @@ -932,7 +936,7 @@ static int mtk_dsi_encoder_init(struct drm_device *drm, struct mtk_dsi *dsi)
>
> dsi->connector = drm_bridge_connector_init(drm, &dsi->encoder);
> if (IS_ERR(dsi->connector)) {
> - DRM_ERROR("Unable to create bridge connector\n");
> + drm_err(drm, "Unable to create bridge connector\n");
> ret = PTR_ERR(dsi->connector);
> goto err_cleanup_encoder;
> }
> @@ -985,6 +989,7 @@ static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
> {
> struct mtk_dsi *dsi = host_to_dsi(host);
> struct device *dev = host->dev;
> + struct drm_device *drm = dsi->bridge.dev;
> int ret;
>
> dsi->lanes = device->lanes;
> @@ -1012,7 +1017,7 @@ static int mtk_dsi_host_attach(struct mipi_dsi_host *host,
>
> ret = component_add(host->dev, &mtk_dsi_component_ops);
> if (ret) {
> - DRM_ERROR("failed to add dsi_host component: %d\n", ret);
> + drm_err(drm, "failed to add dsi_host component: %d\n", ret);
> drm_bridge_remove(&dsi->bridge);
> return ret;
> }
> @@ -1034,11 +1039,12 @@ static void mtk_dsi_wait_for_idle(struct mtk_dsi *dsi)
> {
> int ret;
> u32 val;
> + struct drm_device *drm = dsi->bridge.dev;
>
> ret = readl_poll_timeout(dsi->regs + DSI_INTSTA, val, !(val & DSI_BUSY),
> 4, 2000000);
> if (ret) {
> - DRM_WARN("polling dsi wait not busy timeout!\n");
> + drm_warn(drm, "polling dsi wait not busy timeout!\n");
>
> mtk_dsi_enable(dsi);
> mtk_dsi_reset_engine(dsi);
> @@ -1123,6 +1129,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
> const struct mipi_dsi_msg *msg)
> {
> struct mtk_dsi *dsi = host_to_dsi(host);
> + struct drm_device *drm = dsi->bridge.dev;
> ssize_t recv_cnt;
> u8 read_data[16];
> void *src_addr;
> @@ -1153,7 +1160,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
> }
>
> if (!msg->rx_buf) {
> - DRM_ERROR("dsi receive buffer size may be NULL\n");
> + drm_err(drm, "dsi receive buffer size may be NULL\n");
> ret = -EINVAL;
> goto restore_dsi_mode;
> }
> @@ -1177,7 +1184,7 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
> if (recv_cnt)
> memcpy(msg->rx_buf, src_addr, recv_cnt);
>
> - DRM_INFO("dsi get %zd byte data from the panel address(0x%x)\n",
> + drm_info(drm, "dsi get %zd byte data from the panel address(0x%x)\n",
> recv_cnt, *((u8 *)(msg->tx_buf)));
>
> restore_dsi_mode:
> --
> 2.43.0
>
^ permalink raw reply
* Re: [PATCH v1] virt: arm-cca-guest: use raw variant of smp_processor_id() in arm_cca_report_new()
From: Kohei Enju @ 2026-05-18 13:38 UTC (permalink / raw)
To: Catalin Marinas
Cc: Will Deacon, Sami Mujawar, Gavin Shan, Steven Price,
Suzuki K Poulose, linux-arm-kernel, linux-kernel
In-Reply-To: <agsHBb9f3HkmJaIx@arm.com>
On 05/18 13:33, Catalin Marinas wrote:
> On Mon, May 18, 2026 at 12:31:31PM +0900, Kohei Enju wrote:
> > With CONFIG_DEBUG_PREEMPT=y, smp_processor_id() becomes an alias of
> > debug_smp_processor_id(). This debug function complains when certain
> > conditions that ensure CPU ID stability are not met, specifically when
> > it's called from a preemptible context.
> >
> > In arm_cca_report_new(), which runs in a preemptible context,
> > smp_processor_id() triggers a splat [0] due to this.
> >
> > However, the CPU ID obtained here is used as the target CPU for
> > smp_call_function_single() to designate a specific CPU for subsequent
> > operations, not to assert that the current thread will continue to
> > execute on the same CPU. Therefore, snapshotting the CPU ID itself is
> > correct, and thus there's no actual harm except for the splat.
> >
> > Use raw_smp_processor_id() instead, to directly retrieve the current CPU
> > ID without the debug checks, avoiding the unnecessary warning message
> > while preserving the correct functional behavior.
> >
> > [0]
> > BUG: using smp_processor_id() in preemptible [00000000] code: cca-workload-at/134
> > caller is debug_smp_processor_id+0x20/0x2c
> > CPU: 0 UID: 0 PID: 134 Comm: cca-workload-at Not tainted 7.0.0-rc1-gc74a64d12073 #1 PREEMPT
> > Hardware name: linux,dummy-virt (DT)
> > Call trace:
> > [...]
> > check_preemption_disabled+0xf8/0x100
> > debug_smp_processor_id+0x20/0x2c
> > arm_cca_report_new+0x54/0x230
> > tsm_report_read+0x184/0x260
> > tsm_report_outblob_read+0x18/0x38
> > configfs_bin_read_iter+0xf4/0x1dc
> > vfs_read+0x230/0x31c
> > [...]
> >
> > Fixes: 7999edc484ca ("virt: arm-cca-guest: TSM_REPORT support for realms")
> > Signed-off-by: Kohei Enju <enju.kohei@fujitsu.com>
> > ---
> > drivers/virt/coco/arm-cca-guest/arm-cca-guest.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > index 0c9ea24a200c..2d450caee3e4 100644
> > --- a/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > +++ b/drivers/virt/coco/arm-cca-guest/arm-cca-guest.c
> > @@ -108,7 +108,7 @@ static int arm_cca_report_new(struct tsm_report *report, void *data)
> > * allocate outblob based on the returned value from the 'init'
> > * call and that cannot be done in an atomic context.
> > */
> > - cpu = smp_processor_id();
> > + cpu = raw_smp_processor_id();
>
> That's just hiding the warning which might be genuine, irrespective of
> what the comment says. Sashiko has some good points:
>
> https://sashiko.dev/#/patchset/20260518033157.1865498-1-enju.kohei@fujitsu.com
>
> Basically what guarantees that the cpu won't go offline? Can we use
> migrate_disable() and ignore the smp_call_function_single() altogether?
> It looks like a hack anyway.
Hi Catalin,
Thank you for reviewing.
You've raised a very valid point about raw_smp_processor_id()
potentially hiding a genuine issue. I agree this would be a concern in
most contexts.
However, this implementation was intentionally designed not to block CPU
hotplug:
https://lore.kernel.org/linux-arm-kernel/7a83461d-40fd-4e61-8833-5dae2abaf82b@arm.com/
As mentioned in the thread above, the potential failure from the target
CPU going offline (resulting in -ENXIO) is an expected and tolerated
condition in this path.
Using migrate_disable() would go against the non-blocking design goal.
Given the context, the debug warning looks false positive for our
specific use case to me, and I believe raw_smp_processor_id() correctly
reflects the design intent by simply acquiring a CPU number without
debug checks.
>
> We should also look at the other unrelated findings in this function
Regarding the other unrelated findings by Sashiko, I'll take a look at
them. Thanks for the heads-up.
Thanks,
Kohei
>
> --
> Catalin
>
^ permalink raw reply
* [PATCH] media: stm32: dcmi: avoid double free on video register failure
From: Guangshuo Li @ 2026-05-18 13:23 UTC (permalink / raw)
To: Hugues Fruchet, Alain Volmat, Mauro Carvalho Chehab,
Maxime Coquelin, Alexandre Torgue, Yannick Fertre, Hans Verkuil,
linux-media, linux-stm32, linux-arm-kernel, linux-kernel
Cc: Guangshuo Li
dcmi_probe() allocates a video_device with video_device_alloc() and
releases it from the err_device_release error path if
video_register_device() fails.
This can double free the video_device when __video_register_device()
reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev)
dcmi_probe()
-> err_device_release
-> video_device_release(dcmi->vdev)
Use video_device_release_empty() while registering the device so that
registration failure paths do not free dcmi->vdev through vdev->release().
dcmi_probe() then releases dcmi->vdev exactly once from
err_device_release. Restore video_device_release() after successful
registration so the registered device keeps its normal lifetime handling.
This issue was found by a static analysis tool I am developing.
Fixes: 37404f91ef8b ("[media] stm32-dcmi: STM32 DCMI camera interface driver")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/media/platform/st/stm32/stm32-dcmi.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/st/stm32/stm32-dcmi.c b/drivers/media/platform/st/stm32/stm32-dcmi.c
index 13762861b769..a6918fc618fb 100644
--- a/drivers/media/platform/st/stm32/stm32-dcmi.c
+++ b/drivers/media/platform/st/stm32/stm32-dcmi.c
@@ -1990,7 +1990,7 @@ static int dcmi_probe(struct platform_device *pdev)
dcmi->vdev->v4l2_dev = &dcmi->v4l2_dev;
dcmi->vdev->queue = &dcmi->queue;
strscpy(dcmi->vdev->name, KBUILD_MODNAME, sizeof(dcmi->vdev->name));
- dcmi->vdev->release = video_device_release;
+ dcmi->vdev->release = video_device_release_empty;
dcmi->vdev->ioctl_ops = &dcmi_ioctl_ops;
dcmi->vdev->lock = &dcmi->lock;
dcmi->vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
@@ -2012,6 +2012,7 @@ static int dcmi_probe(struct platform_device *pdev)
dev_err(dcmi->dev, "Failed to register video device\n");
goto err_media_entity_cleanup;
}
+ dcmi->vdev->release = video_device_release;
dev_dbg(dcmi->dev, "Device registered as %s\n",
video_device_node_name(dcmi->vdev));
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 6/9] iommu/arm-smmu-v3: Directly encode simple commands
From: Jason Gunthorpe @ 2026-05-18 13:23 UTC (permalink / raw)
To: Nicolin Chen
Cc: iommu, Jonathan Hunter, Joerg Roedel, linux-arm-kernel,
linux-tegra, Robin Murphy, Thierry Reding, Krishna Reddy,
Will Deacon, David Matlack, Pasha Tatashin, patches,
Pranjal Shrivastava, Samiullah Khawaja, Mostafa Saleh
In-Reply-To: <agqETancvNtL0lXc@Asurada-Nvidia>
On Sun, May 17, 2026 at 08:15:25PM -0700, Nicolin Chen wrote:
> > +static inline struct arm_smmu_cmd arm_smmu_make_cmd_cfgi_all(void)
> > +{
> > + struct arm_smmu_cmd cmd = arm_smmu_make_cmd_op(CMDQ_OP_CFGI_ALL);
> > +
> > + cmd.data[1] |= FIELD_PREP(CMDQ_CFGI_1_RANGE, 31);
>
> Optional, might retain the note:
> /* Cover the entire SID range */
The spec doesn't have a note like this is just defined cfgi_all as
having this encoding.
Jason
^ permalink raw reply
* Re: [PATCH v8 2/4] firmware: ti_sci: add support for restoring IRQs during resume
From: Kumar, Udit @ 2026-05-18 13:22 UTC (permalink / raw)
To: Thomas Richard (TI), Nishanth Menon, Tero Kristo,
Santosh Shilimkar, Michael Turquette, Stephen Boyd, Brian Masney
Cc: Gregory CLEMENT, richard.genoud, Abhash Kumar, Thomas Petazzoni,
linux-arm-kernel, linux-kernel, linux-clk, Dhruva Gole,
Kendall Willis, u-kumar1
In-Reply-To: <20260513-ti-sci-jacinto-s2r-restore-irq-v8-2-195b27f91519@bootlin.com>
On 5/13/2026 6:16 PM, Thomas Richard (TI) wrote:
> Some DM-Firmware are not able to restore the IRQ context after a
> suspend-resume. The IRQ_CONTEXT_LOST firmware capability has been
> introduced to identify this characteristic. In this case the
> responsibility is delegated to the ti_sci driver, which maintains an
> internal list of all requested IRQs. This list is updated on each
> set()/free() operation, and all IRQs are restored during the resume_noirq()
> phase.
>
> Reviewed-by: Dhruva Gole <d-gole@ti.com>
> Reviewed-by: Kendall Willis <k-willis@ti.com>
> Signed-off-by: Thomas Richard (TI) <thomas.richard@bootlin.com>
> ---
> drivers/firmware/ti_sci.c | 201 +++++++++++++++++++++++++++++++++++++++++++---
> drivers/firmware/ti_sci.h | 3 +
> 2 files changed, 192 insertions(+), 12 deletions(-)
>
> diff --git a/drivers/firmware/ti_sci.c b/drivers/firmware/ti_sci.c
> index eaeaaae94142..35ee8cc830c8 100644
> --- a/drivers/firmware/ti_sci.c
> +++ b/drivers/firmware/ti_sci.c
> @@ -12,11 +12,13 @@
> #include <linux/cpu.h>
> #include <linux/debugfs.h>
> #include <linux/export.h>
> +#include <linux/hashtable.h>
> #include <linux/io.h>
> #include <linux/iopoll.h>
> #include <linux/kernel.h>
> #include <linux/mailbox_client.h>
> #include <linux/module.h>
> +#include <linux/mutex.h>
> #include <linux/of.h>
> #include <linux/of_platform.h>
> #include <linux/platform_device.h>
Could you check, recursive header inclusion header warning
In file included from linux/printk.h,
from linux/srcu.h:85
from linux/notifier.h:16
from linux/reboot.h:6
-drivers/firmware/ti_sci.c:31: warning: recursive header inclusion
+drivers/firmware/ti_sci.c:33: warning: recursive header inclusion
> @@ -87,6 +89,16 @@ struct ti_sci_desc {
> int max_msg_size;
> };
>
> +/**
> + * struct ti_sci_irq - Description of allocated irqs
> + * @node: Link to hash table
> + * @desc: Description of the irq
> + */
> +struct ti_sci_irq {
> + struct hlist_node node;
> + struct ti_sci_msg_req_manage_irq desc;
> +};
> +
> /**
> * struct ti_sci_info - Structure representing a TI SCI instance
> * @dev: Device pointer
> @@ -101,6 +113,8 @@ struct ti_sci_desc {
> * @chan_rx: Receive mailbox channel
> * @minfo: Message info
> * @node: list head
> + * @irqs: List of allocated irqs
> + * @irq_lock: Protection for irq hash list
> * @host_id: Host ID
> * @fw_caps: FW/SoC low power capabilities
> * @users: Number of users of this instance
> @@ -118,6 +132,8 @@ struct ti_sci_info {
> struct mbox_chan *chan_rx;
> struct ti_sci_xfers_info minfo;
> struct list_head node;
> + DECLARE_HASHTABLE(irqs, 8);
> + struct mutex irq_lock;
One of script report errors, you might need to document hashtabke.
However warning is unrelated
CHECK: struct mutex definition without commen
> u8 host_id;
> u64 fw_caps;
> /* protected by ti_sci_list_mutex */
> @@ -2301,6 +2317,32 @@ static int ti_sci_manage_irq(const struct ti_sci_handle *handle,
> return ret;
> }
>
[..]
^ permalink raw reply
* Re: [PATCH] ARM: dts: aspeed: g6: Add PWM/Tach controller node
From: Andrew Jeffery @ 2026-05-18 13:21 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
Billy Tsai
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel
In-Reply-To: <20260326-g6-dtsi-v1-1-348e7a0661c2@aspeedtech.com>
On Thu, 26 Mar 2026 18:29:22 +0800, Billy Tsai wrote:
> Introduce a device tree node for the AST2600 PWM/Tach controller.
> Describe register range, clock, reset, and cell configuration.
> Set status to "disabled" by default.
>
> Prepares for enabling PWM and tachometer support on platforms
> utilizing this SoC.
>
> [...]
Thanks, I've applied this to the BMC tree.
--
Andrew Jeffery <andrew@codeconstruct.com.au>
^ permalink raw reply
* Re: [PATCH v4 2/3] arm64: dts: ti: Add k3-am62l3-beaglebadge
From: Nishanth Menon @ 2026-05-18 13:11 UTC (permalink / raw)
To: Judith Mendez
Cc: Vignesh Raghavendra, Tero Kristo, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-kernel, devicetree,
linux-kernel, Andrew Davis, Bryan Brattlof, Jason Kridner,
Robert Nelson
In-Reply-To: <20260515153541.294698-3-jm@ti.com>
On 10:35-20260515, Judith Mendez wrote:
> BeagleBoard.org BeagleBadge is a compact, affordable open source
> hardware single board computer based on the Texas Instruments AM62L3
> SoC designed for IoT and embedded applications with low power
> consumption. Expansion is provided over open standards based headers
> including QWIIC and GPIO interfaces.
>
> https://github.com/beagleboard/BeagleBadge
Why not use https://www.beagleboard.org/boards/beaglebadge ?
>
> Co-developed-by: Andrew Davis <afd@ti.com>
> Signed-off-by: Andrew Davis <afd@ti.com>
> Signed-off-by: Judith Mendez <jm@ti.com>
> ---
> Changelog since v3:
> - Add missing newline in commit message
> - Drop beagleboard URL
> - Drop uneeded header files
> - Add boothph flags in wkup_i2c0 & PMC nodes
> ---
> arch/arm64/boot/dts/ti/Makefile | 1 +
> .../boot/dts/ti/k3-am62l3-beaglebadge.dts | 700 ++++++++++++++++++
> 2 files changed, 701 insertions(+)
> create mode 100644 arch/arm64/boot/dts/ti/k3-am62l3-beaglebadge.dts
>
> diff --git a/arch/arm64/boot/dts/ti/Makefile b/arch/arm64/boot/dts/ti/Makefile
> index 5269c9619b65c..4e377ca011cd8 100644
> --- a/arch/arm64/boot/dts/ti/Makefile
> +++ b/arch/arm64/boot/dts/ti/Makefile
> @@ -41,6 +41,7 @@ dtb-$(CONFIG_ARCH_K3) += k3-am62d2-evm.dtb
>
> # Boards with AM62Lx SoCs
> dtb-$(CONFIG_ARCH_K3) += k3-am62l3-evm.dtb
> +dtb-$(CONFIG_ARCH_K3) += k3-am62l3-beaglebadge.dtb
>
> # Boards with AM62Px SoC
> dtb-$(CONFIG_ARCH_K3) += k3-am62p5-sk.dtb
> diff --git a/arch/arm64/boot/dts/ti/k3-am62l3-beaglebadge.dts b/arch/arm64/boot/dts/ti/k3-am62l3-beaglebadge.dts
> new file mode 100644
> index 0000000000000..30fc9c83b1f44
> --- /dev/null
> +++ b/arch/arm64/boot/dts/ti/k3-am62l3-beaglebadge.dts
> @@ -0,0 +1,700 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * https://www.beagleboard.org/boards/beaglebadge
> + *
> + * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
Seeing the tags, I assume no BeagleBoard.org member contributions?
> + */
> +
> +/dts-v1/;
> +
> +#include <dt-bindings/gpio/gpio.h>
> +#include <dt-bindings/input/input.h>
> +#include <dt-bindings/leds/common.h>
> +#include "k3-am62l3.dtsi"
> +#include "k3-pinctrl.h"
> +
> +/ {
> + compatible = "beagle,am62l3-beaglebadge", "ti,am62l3";
> + model = "BeagleBoard.org BeagleBadge";
> +
> + chosen {
> + stdout-path = &uart0;
> + };
> +
> + aliases {
> + gpio0 = &gpio0;
> + gpio2 = &wkup_gpio0;
> + i2c0 = &i2c0;
> + i2c1 = &i2c1;
> + i2c2 = &i2c2;
> + i2c4 = &wkup_i2c0;
> + mmc1 = &sdhci1;
> + mmc2 = &sdhci2;
> + serial3 = &uart1;
> + usb0 = &usb0;
> + usb1 = &usb1;
is this valid?
git grep of_alias_ driver/usb/
am I missing something?
> + };
> +
> + memory@80000000 {
> + /* 256MB */
> + reg = <0x00000000 0x80000000 0x00000000 0x10000000>;
> + device_type = "memory";
> + bootph-all;
> + };
> +
> + thermal-zones {
> + wkup0-thermal {
> + polling-delay-passive = <250>; /* milliSeconds */
> + polling-delay = <500>; /* milliSeconds */
> + thermal-sensors = <&vtm0 0>;
> +
> + trips {
> + crit0 {
> + temperature = <125000>;
> + hysteresis = <2000>;
> + type = "critical";
> + };
> + };
> + };
> + };
This is better done by having something like
arch/arm64/boot/dts/ti/k3-am62l-industrial-thermal.dtsi
[..]
> +
> + sensor_3v3: regulator-4 {
> + /* TPS22918DBVR */
> + compatible = "regulator-fixed";
> + regulator-name = "Sensor_3V3";
> + regulator-min-microvolt = <3300000>;
> + regulator-max-microvolt = <3300000>;
> + vin-supply = <&vdd_3v3>;
> + regulator-boot-on;
> + regulator-always-on;
Why sensor supply is always on?
> + enable-active-high;
> + gpio = <&wkup_gpio0 1 GPIO_ACTIVE_HIGH>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&sensor_3v3_ena_pins_default>;
> + bootph-all;
> + };
> +
> + wlan_en: regulator-5 {
> + compatible = "regulator-fixed";
> + regulator-name = "wlan_en";
> + regulator-min-microvolt = <1800000>;
> + regulator-max-microvolt = <1800000>;
> + enable-active-high;
> + gpios = <&gpio0 51 GPIO_ACTIVE_HIGH>;
> + pinctrl-names = "default";
> + pinctrl-0 = <&wlan_en_pins_default>;
> + };
> +};
> +
[..]
> +
> + usr_button_pins_default: usr-button-default-pins {
> + pinctrl-single,pins = <
> + AM62LX_IOPAD(0x00a4, PIN_INPUT, 7) /* (H18) GPMC0_AD11.GPIO0_26 */
> + AM62LX_IOPAD(0x01e4, PIN_INPUT, 7) /* (D16) EXT_REFCLK1.GPIO0_104 */
> + AM62LX_IOPAD(0x00c0, PIN_INPUT, 7) /* (N19) GPMC0_ADVn_ALE.GPIO0_32 */
> + AM62LX_IOPAD(0x00e8, PIN_INPUT, 7) /* (L19) GPMC0_CSn1.GPIO0_42 */
> + AM62LX_IOPAD(0x00b8, PIN_INPUT, 7) /* (L21) GPMC0_CLK.GPIO0_31 */
> + AM62LX_IOPAD(0x01c0, PIN_INPUT, 7) /* (B13) UART0_RTSn.GPIO0_95 */
> + >;
> + };
no wakeup from usr buttons?
[...]
> +};
> +
> +&gpio0 {
> + gpio-line-names ="","","","","","","","","","", /* 0-9 */
space after that =
> + "","","","","","BOOST_5V_ENA","VDD_3V3_SD_ENA","","","", /* 10-19 */
> + "","","","","","MCP23S18_RESET","BTN_SELECT","","","", /* 20-29 */
> + "","BTN_LEFT","BTN_UP","","LORA_RESET","","","","","", /* 30-39 */
> + "FUEL_GAUGE_BATLOW","LORA_RFSW","BTN_DOWN","USB_HUB_RST","MIKROBUS_INT","","","","","", /* 40-49 */
> + "","WLAN_EN","","","","","","","","", /* 50-59 */
> + "","","","","","","","","","", /* 60-69 */
> + "","","","","","","","","","", /* 70-79 */
> + "","","","","MIKROBUS_RST","","","","LORA_BUSY","", /* 80-89 */
> + "","","","","LORA_DIO","BTN_RIGHT","","","","", /* 90-99 */
> + "","","","","BTN_BACK","","","","","", /* 100-109 */
> + "","","","","","","","","","", /* 110-119 */
> + "","","SD_CD","","",""; /* 120-125 */
Could you keep these under 100 chars?
> + pinctrl-names = "default";
> + pinctrl-0 = <&gpio0_pins_default>, <&usr_button_pins_default>, <&lora_control_pins_default>;
> + bootph-all;
> + status = "okay";
> +};
> +
> +&wkup_gpio0 {
> + gpio-line-names ="","SENSOR_3V3_ENA","","","","","",""; /* 0-7 */
same
> + bootph-all;
> + status = "okay";
> +};
> +
> +&sdhci1 {
> + /* SD/MMC */
> + vmmc-supply = <&vdd_3v3_sd>;
> + disable-wp;
> + cd-gpios = <&gpio0 122 GPIO_ACTIVE_LOW>;
> + cd-debounce-delay-ms = <100>;
> + ti,fails-without-test-cd;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc1_pins_default>;
> + bootph-all;
> + status = "okay";
> +};
> +
> +&sdhci2 {
> + vmmc-supply = <&wlan_en>;
> + bus-width = <4>;
> + non-removable;
> + cap-power-off-card;
> + keep-power-in-suspend;
> + pinctrl-names = "default";
> + pinctrl-0 = <&mmc2_pins_default>;
> + ti,driver-strength-ohm = <50>;
> + ti,fails-without-test-cd;
> + status = "okay";
> +};
Why not introduce the sdhci2 and supplies once we get wlan driver in
upstream?
[...]
--
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D
https://ti.com/opensource
^ permalink raw reply
* [PATCH] media: s5p-mfc: avoid double free on video register failure
From: Guangshuo Li @ 2026-05-18 13:09 UTC (permalink / raw)
To: Marek Szyprowski, Andrzej Hajda, Mauro Carvalho Chehab,
Joonyoung Shim, Kamil Debski, linux-arm-kernel, linux-media,
linux-kernel
Cc: Guangshuo Li
s5p_mfc_probe() allocates video_device instances for both the decoder
and encoder and releases them from the probe error paths if
video_register_device() fails.
This can double free a video_device when __video_register_device()
reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev)
s5p_mfc_probe()
-> err_dec_reg or err_enc_reg
-> video_device_release(vdev)
Use video_device_release_empty() while registering the decoder and encoder
video devices so that registration failure paths do not free them through
vdev->release(). s5p_mfc_probe() then releases each video_device exactly
once from its error path. Restore video_device_release() after successful
registration so the registered devices keep their normal lifetime
handling.
This issue was found by a static analysis tool I am developing.
Fixes: d0ce898c39bf ("[media] s5p-mfc: Replaced commas with semicolons")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
index 32eb402d439c..75abb0a8b7a9 100644
--- a/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/samsung/s5p-mfc/s5p_mfc.c
@@ -1376,7 +1376,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
}
vfd->fops = &s5p_mfc_fops;
vfd->ioctl_ops = get_dec_v4l2_ioctl_ops();
- vfd->release = video_device_release;
+ vfd->release = video_device_release_empty;
vfd->lock = &dev->mfc_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->vfl_dir = VFL_DIR_M2M;
@@ -1395,7 +1395,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
}
vfd->fops = &s5p_mfc_fops;
vfd->ioctl_ops = get_enc_v4l2_ioctl_ops();
- vfd->release = video_device_release;
+ vfd->release = video_device_release_empty;
vfd->lock = &dev->mfc_mutex;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->vfl_dir = VFL_DIR_M2M;
@@ -1416,6 +1416,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
goto err_dec_reg;
}
+
+ dev->vfd_dec->release = video_device_release;
v4l2_info(&dev->v4l2_dev,
"decoder registered as /dev/video%d\n", dev->vfd_dec->num);
@@ -1424,6 +1426,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
goto err_enc_reg;
}
+
+ dev->vfd_enc->release = video_device_release;
v4l2_info(&dev->v4l2_dev,
"encoder registered as /dev/video%d\n", dev->vfd_enc->num);
--
2.43.0
^ permalink raw reply related
* Re: [PATCH] ARM: dts: aspeed: anacapa: Enable MCTP and FRU for NIC
From: Andrew Jeffery @ 2026-05-18 13:09 UTC (permalink / raw)
To: Andy.Chung, Colin Huang
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Joel Stanley,
devicetree, linux-arm-kernel, linux-aspeed, linux-kernel
In-Reply-To: <20260327-dts_enable_nic_mctp-v1-1-5b5c05f4442c@amd.com>
Hi Andy,
Sorry for the delay.
On Fri, 2026-03-27 at 14:59 +0800, Andy Chung via B4 Relay wrote:
> From: Andy Chung <Andy.Chung@amd.com>
>
> Add the mctp-controller property to enable frontend NIC management
> via PLDM over MCTP.
> Also add EEPROM device for NIC FRU.
>
> Signed-off-by: Andy Chung <Andy.Chung@amd.com>
> ---
> Add the mctp-controller property to enable frontend NIC management
> via PLDM over MCTP.
> Also add EEPROM device for NIC FRU.
> ---
> .../dts/aspeed/aspeed-bmc-facebook-anacapa.dts | 67 +++++++++++++++++++++-
> 1 file changed, 65 insertions(+), 2 deletions(-)
Do you mind coordinating with Colin on this one, as he's rearranging
the Anacapa devicetrees.
Cheers,
Andrew
>
> diff --git a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> index 221af858cb6b..138b081be049 100644
> --- a/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> +++ b/arch/arm/boot/dts/aspeed/aspeed-bmc-facebook-anacapa.dts
> @@ -584,38 +584,67 @@ eeprom@56 {
> // R Bridge Board
> &i2c10 {
> status = "okay";
> + multi-master;
> + mctp@10 {
> + compatible = "mctp-i2c-controller";
> + reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> + };
>
> i2c-mux@71 {
> compatible = "nxp,pca9548";
> reg = <0x71>;
> #address-cells = <1>;
> #size-cells = <0>;
> - i2c-mux-idle-disconnect;
>
> i2c10mux0ch0: i2c@0 {
> reg = <0>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> };
> i2c10mux0ch1: i2c@1 {
> reg = <1>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c10mux0ch2: i2c@2 {
> reg = <2>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c10mux0ch3: i2c@3 {
> reg = <3>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c10mux0ch4: i2c@4 {
> reg = <4>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c10mux0ch5: i2c@5 {
> reg = <5>;
> @@ -661,38 +690,72 @@ i2c10mux0ch7: i2c@7 {
> // L Bridge Board
> &i2c11 {
> status = "okay";
> + multi-master;
> + mctp@10 {
> + compatible = "mctp-i2c-controller";
> + reg = <(0x10 | I2C_OWN_SLAVE_ADDRESS)>;
> + };
>
> i2c-mux@71 {
> compatible = "nxp,pca9548";
> reg = <0x71>;
> #address-cells = <1>;
> #size-cells = <0>;
> - i2c-mux-idle-disconnect;
>
> i2c11mux0ch0: i2c@0 {
> reg = <0>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // FE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c11mux0ch1: i2c@1 {
> reg = <1>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c11mux0ch2: i2c@2 {
> reg = <2>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c11mux0ch3: i2c@3 {
> reg = <3>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c11mux0ch4: i2c@4 {
> reg = <4>;
> #address-cells = <1>;
> #size-cells = <0>;
> + mctp-controller;
> + // BE NIC FRU
> + eeprom@50 {
> + compatible = "atmel,24c32";
> + reg = <0x50>;
> + };
> };
> i2c11mux0ch5: i2c@5 {
> reg = <5>;
>
> ---
> base-commit: 6de23f81a5e08be8fbf5e8d7e9febc72a5b5f27f
> change-id: 20260327-dts_enable_nic_mctp-e35a5765b176
>
> Best regards,
> --
> Andy Chung <Andy.Chung@amd.com>
>
^ permalink raw reply
* Re: [PATCH] ARM: dts: aspeed: g6: Add missing uart nodes
From: Andrew Jeffery @ 2026-05-18 13:04 UTC (permalink / raw)
To: Jammy Huang, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Joel Stanley
Cc: devicetree, linux-arm-kernel, linux-aspeed, linux-kernel
In-Reply-To: <20260327-upstream_g6_dts_uart-v1-1-26e72b47bc97@aspeedtech.com>
Hi Jammy,
Sorry for the delay.
On Fri, 2026-03-27 at 09:58 +0800, Jammy Huang wrote:
> Add nodes for uart10/11/12/13.
>
> Signed-off-by: Jammy Huang <jammy_huang@aspeedtech.com>
> ---
> arch/arm/boot/dts/aspeed/aspeed-g6.dtsi | 56 +++++++++++++++++++++++++++++++++
> 1 file changed, 56 insertions(+)
Do you mind rebasing this on bmc/linux.git aspeed/arm/dt to fix the
conflict and re-sending it?
Cheers,
Andrew
^ permalink raw reply
* [PATCH] media: imx-jpeg: avoid double free on video register failure
From: Guangshuo Li @ 2026-05-18 13:02 UTC (permalink / raw)
To: Mirela Rabulea, Mauro Carvalho Chehab, Frank Li, Sascha Hauer,
Pengutronix Kernel Team, Fabio Estevam, Hans Verkuil, imx,
linux-media, linux-arm-kernel, linux-kernel
Cc: Guangshuo Li
mxc_jpeg_probe() allocates a video_device with video_device_alloc() and
releases it from the err_vdev_register error path if
video_register_device() fails.
This can double free the video_device when __video_register_device()
reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev)
mxc_jpeg_probe()
-> err_vdev_register
-> video_device_release(jpeg->dec_vdev)
Use video_device_release_empty() while registering the device so that
registration failure paths do not free jpeg->dec_vdev through
vdev->release(). mxc_jpeg_probe() then releases jpeg->dec_vdev exactly
once from err_vdev_register. Restore video_device_release() after
successful registration so the registered device keeps its normal lifetime
handling.
This issue was found by a static analysis tool I am developing.
Fixes: 2db16c6ed72c ("media: imx-jpeg: Add V4L2 driver for i.MX8 JPEG Encoder/Decoder")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
index b442dcba02e7..fe8a373576ef 100644
--- a/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
+++ b/drivers/media/platform/nxp/imx-jpeg/mxc-jpeg.c
@@ -2943,7 +2943,7 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
jpeg->dec_vdev->fops = &mxc_jpeg_fops;
jpeg->dec_vdev->ioctl_ops = &mxc_jpeg_ioctl_ops;
jpeg->dec_vdev->minor = -1;
- jpeg->dec_vdev->release = video_device_release;
+ jpeg->dec_vdev->release = video_device_release_empty;
jpeg->dec_vdev->lock = &jpeg->lock; /* lock for ioctl serialization */
jpeg->dec_vdev->v4l2_dev = &jpeg->v4l2_dev;
jpeg->dec_vdev->vfl_dir = VFL_DIR_M2M;
@@ -2962,6 +2962,8 @@ static int mxc_jpeg_probe(struct platform_device *pdev)
dev_err(dev, "failed to register video device\n");
goto err_vdev_register;
}
+ jpeg->dec_vdev->release = video_device_release;
+
if (mode == MXC_JPEG_ENCODE)
v4l2_info(&jpeg->v4l2_dev,
"encoder device registered as /dev/video%d (%d,%d)\n",
--
2.43.0
^ permalink raw reply related
* Re: [RFC PATCH v4 00/14] coco/TSM: Host-side Arm CCA IDE setup via connect/disconnect callbacks
From: Will Deacon @ 2026-05-18 12:59 UTC (permalink / raw)
To: Aneesh Kumar K.V (Arm)
Cc: linux-coco, kvmarm, linux-arm-kernel, linux-kernel,
Alexey Kardashevskiy, Catalin Marinas, Dan Williams,
Jason Gunthorpe, Jonathan Cameron, Marc Zyngier, Samuel Ortiz,
Steven Price, Suzuki K Poulose, Xu Yilun
In-Reply-To: <20260427065121.916615-1-aneesh.kumar@kernel.org>
On Mon, Apr 27, 2026 at 12:21:07PM +0530, Aneesh Kumar K.V (Arm) wrote:
> arch/arm64/include/asm/rmi_cmds.h | 85 +++
> arch/arm64/include/asm/rmi_smc.h | 168 +++++
Curious, but why does this stuff have to live in the arch code? Wouldn't
it be better off somewhere like drivers/firmware/ or
include/linux/arm-rmi.h?
Will
^ permalink raw reply
* Re: [PATCH v12 06/15] kasan: arm64: x86: Make page_to_virt() KASAN aware
From: Maciej Wieczor-Retman @ 2026-05-18 12:59 UTC (permalink / raw)
To: Will Deacon
Cc: Maciej Wieczor-Retman, Catalin Marinas, Andrey Ryabinin,
Alexander Potapenko, Andrey Konovalov, Dmitry Vyukov,
Vincenzo Frascino, Andrew Morton, David Hildenbrand,
Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, linux-arm-kernel, linux-kernel,
kasan-dev, linux-mm
In-Reply-To: <agr-g38q5RiahqaA@willie-the-truck>
On 2026-05-18 at 12:56:51 +0100, Will Deacon wrote:
>On Mon, Mar 30, 2026 at 02:33:43PM +0000, Maciej Wieczor-Retman wrote:
>> From: Maciej Wieczor-Retman <maciej.wieczor-retman@intel.com>
>> diff --git a/arch/arm64/include/asm/memory.h b/arch/arm64/include/asm/memory.h
>> index 875c0bd0d85a..39dd0071d3ec 100644
>> --- a/arch/arm64/include/asm/memory.h
>> +++ b/arch/arm64/include/asm/memory.h
>> @@ -411,11 +411,6 @@ static inline unsigned long virt_to_pfn(const void *kaddr)
>> */
>>
>> #if defined(CONFIG_DEBUG_VIRTUAL)
>> -#define page_to_virt(x) ({ \
>> - __typeof__(x) __page = x; \
>> - void *__addr = __va(page_to_phys(__page)); \
>> - (void *)__tag_set((const void *)__addr, page_kasan_tag(__page));\
>> -})
>
>So here we're using '__page' to avoid multiple evaluations of 'x'...
>
...
>> diff --git a/include/linux/mm.h b/include/linux/mm.h
>> index 09044934dda8..f234650a4edf 100644
>> --- a/include/linux/mm.h
>> +++ b/include/linux/mm.h
>> @@ -117,7 +117,10 @@ extern int mmap_rnd_compat_bits __read_mostly;
>> #endif
>>
>> #ifndef page_to_virt
>> -#define page_to_virt(x) __va(PFN_PHYS(page_to_pfn(x)))
>> +#define page_to_virt(x) ({ \
>> + void *__addr = __va(PFN_PHYS(page_to_pfn((struct page *)x))); \
>> + kasan_set_tag(__addr, page_kasan_tag(x)); \
>> +})
>
>... but in the new code you're proposing, you evaluate 'x' twice.
>
>Is there a reason not to take the arm64 code as-is?
>
>Will
I was going for less lines in this macro when I initially wrote it. But you're
right, the arm64 version is better, I'll switch to it.
Thanks!
--
Kind regards
Maciej Wieczór-Retman
^ permalink raw reply
* Re: [PATCH] PCI: meson: Propagate devm_add_action_or_reset() failure
From: Neil Armstrong @ 2026-05-18 12:56 UTC (permalink / raw)
To: Shuvam Pandey, Yue Wang,
Lorenzo Pieralisi <lpieralisi@kernel.org>,
Manivannan Sadhasivam, Rob Herring, Bjorn Helgaas, Kevin Hilman,
Jerome Brunet, Martin Blumenstingl
Cc: linux-pci, linux-amlogic, linux-arm-kernel, linux-kernel
In-Reply-To: <177909148011.9588.6639767953842842291@gmail.com>
On 5/18/26 10:04, Shuvam Pandey wrote:
> meson_pcie_probe_clock() enables a clock and then registers a devres
> action to disable it during teardown. If devm_add_action_or_reset()
> fails, it runs the action immediately, disabling the clock.
>
> The return value is currently ignored, so on that failure path
> meson_pcie_probe_clock() returns the disabled clock and probe continues.
> Return the error so the existing probe error path unwinds normally.
>
> Fixes: 9c0ef6d34fdbf ("PCI: amlogic: Add the Amlogic Meson PCIe controller driver")
> Signed-off-by: Shuvam Pandey <shuvampandey1@gmail.com>
> ---
> drivers/pci/controller/dwc/pci-meson.c | 4 +++-
> 1 file changed, 3 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/pci/controller/dwc/pci-meson.c b/drivers/pci/controller/dwc/pci-meson.c
> index 0694084f612b..8d495bcc3a41 100644
> --- a/drivers/pci/controller/dwc/pci-meson.c
> +++ b/drivers/pci/controller/dwc/pci-meson.c
> @@ -204,7 +204,9 @@ static inline struct clk *meson_pcie_probe_clock(struct device *dev,
> return ERR_PTR(ret);
> }
>
> - devm_add_action_or_reset(dev, meson_pcie_disable_clock, clk);
> + ret = devm_add_action_or_reset(dev, meson_pcie_disable_clock, clk);
> + if (ret)
> + return ERR_PTR(ret);
>
> return clk;
> }
Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
Thanks,
Neil
^ permalink raw reply
* [PATCH] media: mediatek: mdp: avoid double free on video register failure
From: Guangshuo Li @ 2026-05-18 12:55 UTC (permalink / raw)
To: Minghsiu Tsai, Houlong Wei, Andrew-CT Chen, Mauro Carvalho Chehab,
Matthias Brugger, AngeloGioacchino Del Regno, Hans Verkuil,
linux-media, linux-kernel, linux-arm-kernel, linux-mediatek
Cc: Guangshuo Li
mtk_mdp_register_m2m_device() allocates a video_device with
video_device_alloc() and releases it from the err_m2m_init error path if
video_register_device() fails.
This can double free the video_device when __video_register_device()
reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev)
mtk_mdp_register_m2m_device()
-> err_m2m_init
-> video_device_release(mdp->vdev)
Use video_device_release_empty() while registering the device so that
registration failure paths do not free mdp->vdev through vdev->release().
mtk_mdp_register_m2m_device() then releases mdp->vdev exactly once from
err_m2m_init. Restore video_device_release() after successful registration
so the registered device keeps its normal lifetime handling.
Clear mdp->vdev after releasing it on failure to avoid leaving a stale
pointer behind.
This issue was found by a static analysis tool I am developing.
Fixes: 7febb418a32a ("[media] mtk-mdp: allocate video_device dynamically")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
index d2813890cceb..5cc80a542eda 100644
--- a/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
+++ b/drivers/media/platform/mediatek/mdp/mtk_mdp_m2m.c
@@ -1185,7 +1185,7 @@ int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
mdp->vdev->device_caps = V4L2_CAP_VIDEO_M2M_MPLANE | V4L2_CAP_STREAMING;
mdp->vdev->fops = &mtk_mdp_m2m_fops;
mdp->vdev->ioctl_ops = &mtk_mdp_m2m_ioctl_ops;
- mdp->vdev->release = video_device_release;
+ mdp->vdev->release = video_device_release_empty;
mdp->vdev->lock = &mdp->lock;
mdp->vdev->vfl_dir = VFL_DIR_M2M;
mdp->vdev->v4l2_dev = &mdp->v4l2_dev;
@@ -1205,6 +1205,7 @@ int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
dev_err(dev, "failed to register video device\n");
goto err_vdev_register;
}
+ mdp->vdev->release = video_device_release;
v4l2_info(&mdp->v4l2_dev, "driver registered as /dev/video%d",
mdp->vdev->num);
@@ -1213,7 +1214,8 @@ int mtk_mdp_register_m2m_device(struct mtk_mdp_dev *mdp)
err_vdev_register:
v4l2_m2m_release(mdp->m2m_dev);
err_m2m_init:
- video_device_release(mdp->vdev);
+ video_device_release(mdp->vdev)
+ mdp->vdev = NULL;
err_video_alloc:
return ret;
--
2.43.0
^ permalink raw reply related
* [PATCH] media: mediatek: jpeg: avoid double free on video register failure
From: Guangshuo Li @ 2026-05-18 12:51 UTC (permalink / raw)
To: Bin Liu, Mauro Carvalho Chehab, Matthias Brugger,
AngeloGioacchino Del Regno, Tomasz Figa, Hans Verkuil, Xia Jiang,
linux-media, linux-kernel, linux-arm-kernel, linux-mediatek
Cc: Guangshuo Li
mtk_jpeg_probe() allocates a video_device with video_device_alloc() and
releases it from the err_vfd_jpeg_register error path if
video_register_device() fails.
This can double free the video_device when __video_register_device()
reaches device_register() and that call fails:
video_register_device()
-> __video_register_device()
-> device_register() fails
-> put_device(&vdev->dev)
-> v4l2_device_release()
-> vdev->release(vdev)
-> video_device_release(vdev)
mtk_jpeg_probe()
-> err_vfd_jpeg_register
-> video_device_release(jpeg->vdev)
Use video_device_release_empty() while registering the device so that
registration failure paths do not free jpeg->vdev through vdev->release().
mtk_jpeg_probe() then releases jpeg->vdev exactly once from
err_vfd_jpeg_register. Restore video_device_release() after successful
registration so the registered device keeps its normal lifetime handling.
This issue was found by a static analysis tool I am developing.
Fixes: 2ac8015f156b ("media: platform: Rename existing functions/defines/variables")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
index c01124a349f6..9888ac8dd6e4 100644
--- a/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
+++ b/drivers/media/platform/mediatek/jpeg/mtk_jpeg_core.c
@@ -1362,7 +1362,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
jpeg->vdev->fops = &mtk_jpeg_fops;
jpeg->vdev->ioctl_ops = jpeg->variant->ioctl_ops;
jpeg->vdev->minor = -1;
- jpeg->vdev->release = video_device_release;
+ jpeg->vdev->release = video_device_release_empty;
jpeg->vdev->lock = &jpeg->lock;
jpeg->vdev->v4l2_dev = &jpeg->v4l2_dev;
jpeg->vdev->vfl_dir = VFL_DIR_M2M;
@@ -1374,6 +1374,7 @@ static int mtk_jpeg_probe(struct platform_device *pdev)
v4l2_err(&jpeg->v4l2_dev, "Failed to register video device\n");
goto err_vfd_jpeg_register;
}
+ jpeg->vdev->release = video_device_release;
video_set_drvdata(jpeg->vdev, jpeg);
v4l2_info(&jpeg->v4l2_dev,
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v2 3/3] arm64: dts: allwinner: A133: add support for Baijie Helper A133 board
From: Andre Przywara @ 2026-05-18 12:50 UTC (permalink / raw)
To: Alexander Sverdlin, linux-sunxi
Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Chen-Yu Tsai,
Jernej Skrabec, Samuel Holland, devicetree, linux-arm-kernel,
linux-kernel
In-Reply-To: <6d8659f393e0bb4f0805107a17e306422982247c.camel@gmail.com>
Hi,
On 5/18/26 13:29, Alexander Sverdlin wrote:
> Hi Andre,
>
> On Mon, 2026-05-18 at 13:16 +0200, Andre Przywara wrote:
>>>> And anyway, I see a *dual* USB-A socket on the pictures online, in
>>>> addition to the USB-OTG port. So where does the third USB come from? The
>>>> A133 only supports one host USB port plus the one OTG port. So is there
>>>> an USB hub chip on the board?
>>>
>>> There are two hubs, one on each usbphy. OTG side hub is even bus-powered,
>>
>> What do you mean with OTG side hub, exactly? Is there a hub on USB0? How
>> does this work, then?
>
> the upstream port of this hub is wired to the USB-C connector, one port has
> CH340E USB-UART on it for the console, the other port goes to the SoC usbphy 0.
> So it would be "peripheral" only, I suppose.
Ah, that's interesting, I was wondering about this, but don't think we
have seen this before.
So yeah, then it's definitely peripheral only. And please state in the
comment that it's connected to the downstream port of a hub, so changing
it to "host" will not work.
Thanks,
Andre
^ permalink raw reply
* Re: [PATCH v4 0/3] arm64: dts/bindings: Add support for BeagleBadge
From: Nishanth Menon @ 2026-05-18 12:49 UTC (permalink / raw)
To: Judith Mendez
Cc: Vignesh Raghavendra, Tero Kristo, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, linux-arm-kernel, devicetree,
linux-kernel, Andrew Davis, Bryan Brattlof, Jason Kridner,
Robert Nelson
In-Reply-To: <20260515153541.294698-1-jm@ti.com>
On 10:35-20260515, Judith Mendez wrote:
> Hi,
>
> BeagleBoard.org BeagleBadge[1] is a compact, affordable open source
> hardware [2] single board computer based on the Texas Instruments AM62L3
> SoC designed for IoT and embedded applications. Add base support for
> the same.
>
> SD boot:
> Link: https://gist.github.com/jmenti/8818fa277597de927dd2b42ab1d2552f
in all patches,
Is https://www.beagleboard.org/boards/beaglebadge a better canonical
link?
Robert/Jason: for some reason https://www.beagleboard.org/boards does'nt
list it. Is there a reason?
>
> This patch series adds:
> - Device tree bindings update for am62l3-badge
> - Device tree source for BeagleBadge board
> - Defconfig: drivers for BeagleBadge
>
> Changelog since v3:
> - Fix newline in commit messages
> - Drop vendor URLs
> DTS:
> - Add bootph flags in wakup i2c & PMIC nodes for completeness
> - Drop unneeded header files
>
> v3
> Link: https://lore.kernel.org/all/20260513233447.2713737-1-jm@ti.com/
> V2
> Link: https://lore.kernel.org/all/20260508230341.1891450-1-jm@ti.com/
> V1
> Link: https://lore.kernel.org/all/20260501233148.4180391-1-jm@ti.com/
>
> Patch series depends on:
> Link: https://lore.kernel.org/all/20260513231154.2703292-1-jm@ti.com/
>
> [1] https://www.beagleboard.org/boards/beaglebadge
> [2] https://github.com/beagleboard/BeagleBadge/blob/main/design/BeagleBadge_RevA_V0.7_SCH_251107.pdf
>
> Judith Mendez (3):
> dt-bindings: arm: ti: Add am62l3-beaglebadge
> arm64: dts: ti: Add k3-am62l3-beaglebadge
> arm64: defconfig: Enable drivers for BeagleBadge
>
> .../devicetree/bindings/arm/ti/k3.yaml | 1 +
> arch/arm64/boot/dts/ti/Makefile | 1 +
> .../boot/dts/ti/k3-am62l3-beaglebadge.dts | 700 ++++++++++++++++++
> arch/arm64/configs/defconfig | 5 +
> 4 files changed, 707 insertions(+)
> create mode 100644 arch/arm64/boot/dts/ti/k3-am62l3-beaglebadge.dts
>
> --
> 2.54.0
>
--
Regards,
Nishanth Menon
Key (0xDDB5849D1736249D) / Fingerprint: F8A2 8693 54EB 8232 17A3 1A34 DDB5 849D 1736 249D
https://ti.com/opensource
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox