[RFC] firmware: arm_scmi: support clock denied attributes

Peng Fan (OSS) peng.fan at oss.nxp.com
Wed Oct 25 20:41:25 PDT 2023


From: Peng Fan <peng.fan at nxp.com>

This is not in SPEC and is just defined by NXP. This patch is
to start the discussion to start include them in SPEC.

Signed-off-by: Peng Fan <peng.fan at nxp.com>
---
 drivers/clk/clk-scmi.c            | 39 +++++++++++++++++++++++++------
 drivers/firmware/arm_scmi/clock.c |  9 +++++++
 include/linux/scmi_protocol.h     |  4 ++++
 3 files changed, 45 insertions(+), 7 deletions(-)

diff --git a/drivers/clk/clk-scmi.c b/drivers/clk/clk-scmi.c
index 8cbe24789c24..303f8a8ec8e0 100644
--- a/drivers/clk/clk-scmi.c
+++ b/drivers/clk/clk-scmi.c
@@ -75,15 +75,13 @@ static int scmi_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 			     unsigned long parent_rate)
 {
 	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+	u64 rate1 = 0;
 
-	return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
-}
-
-static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
-{
-	struct scmi_clk *clk = to_scmi_clk(hw);
+	if (info->flags & SCMI_CLOCK_SET_RATE_DENIED)
+		return -EACCES;
 
-	return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
+	return scmi_proto_clk_ops->rate_set(clk->ph, clk->id, rate);
 }
 
 static u8 scmi_clk_get_parent(struct clk_hw *hw)
@@ -107,6 +105,17 @@ static u8 scmi_clk_get_parent(struct clk_hw *hw)
 	return p_idx;
 }
 
+static int scmi_clk_set_parent(struct clk_hw *hw, u8 parent_index)
+{
+	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+
+	if (info->flags & SCMI_CLOCK_SET_ENABLE_DENIED)
+		return -EACCES;
+
+	return scmi_proto_clk_ops->parent_set(clk->ph, clk->id, parent_index);
+}
+
 static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
 {
 	/*
@@ -119,6 +128,10 @@ static int scmi_clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *r
 static int scmi_clk_enable(struct clk_hw *hw)
 {
 	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+
+	if (info->flags & SCMI_CLOCK_SET_ENABLE_DENIED)
+		return 0;
 
 	return scmi_proto_clk_ops->enable(clk->ph, clk->id, NOT_ATOMIC);
 }
@@ -126,6 +139,10 @@ static int scmi_clk_enable(struct clk_hw *hw)
 static void scmi_clk_disable(struct clk_hw *hw)
 {
 	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+
+	if (info->flags & SCMI_CLOCK_SET_ENABLE_DENIED)
+		return;
 
 	scmi_proto_clk_ops->disable(clk->ph, clk->id, NOT_ATOMIC);
 }
@@ -133,6 +150,10 @@ static void scmi_clk_disable(struct clk_hw *hw)
 static int scmi_clk_atomic_enable(struct clk_hw *hw)
 {
 	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+
+	if (info->flags & SCMI_CLOCK_SET_ENABLE_DENIED)
+		return 0;
 
 	return scmi_proto_clk_ops->enable(clk->ph, clk->id, ATOMIC);
 }
@@ -140,6 +161,10 @@ static int scmi_clk_atomic_enable(struct clk_hw *hw)
 static void scmi_clk_atomic_disable(struct clk_hw *hw)
 {
 	struct scmi_clk *clk = to_scmi_clk(hw);
+	const struct scmi_clock_info *info = clk->info;
+
+	if (info->flags & SCMI_CLOCK_SET_ENABLE_DENIED)
+		return;
 
 	scmi_proto_clk_ops->disable(clk->ph, clk->id, ATOMIC);
 }
diff --git a/drivers/firmware/arm_scmi/clock.c b/drivers/firmware/arm_scmi/clock.c
index 42b81c181d68..1a62e3b82d34 100644
--- a/drivers/firmware/arm_scmi/clock.c
+++ b/drivers/firmware/arm_scmi/clock.c
@@ -46,6 +46,9 @@ struct scmi_msg_resp_clock_attributes {
 #define SUPPORTS_RATE_CHANGE_REQUESTED_NOTIF(x)	((x) & BIT(30))
 #define SUPPORTS_EXTENDED_NAMES(x)		((x) & BIT(29))
 #define SUPPORTS_PARENT_CLOCK(x)		((x) & BIT(28))
+#define SETS_ENABLE_DENIED(x)			((x) & BIT(15))
+#define SETS_RATE_DENIED(x)			((x) & BIT(14))
+#define SETS_PARENT_DENIED(x)			((x) & BIT(13))
 	u8 name[SCMI_SHORT_NAME_MAX_SIZE];
 	__le32 clock_enable_latency;
 };
@@ -327,6 +330,12 @@ static int scmi_clock_attributes_get(const struct scmi_protocol_handle *ph,
 			clk->rate_change_requested_notifications = true;
 		if (SUPPORTS_PARENT_CLOCK(attributes))
 			scmi_clock_possible_parents(ph, clk_id, clk);
+		if (SETS_PARENT_DENIED(attributes))
+			clk->flags |= SCMI_CLOCK_SET_PARENT_DENIED;
+		if (SETS_RATE_DENIED(attributes))
+			clk->flags |= SCMI_CLOCK_SET_RATE_DENIED;
+		if (SETS_ENABLE_DENIED(attributes))
+			clk->flags |= SCMI_CLOCK_SET_ENABLE_DENIED;
 	}
 
 	return ret;
diff --git a/include/linux/scmi_protocol.h b/include/linux/scmi_protocol.h
index f2f05fb42d28..71911dcd8117 100644
--- a/include/linux/scmi_protocol.h
+++ b/include/linux/scmi_protocol.h
@@ -41,12 +41,16 @@ struct scmi_revision_info {
 	char sub_vendor_id[SCMI_SHORT_NAME_MAX_SIZE];
 };
 
+#define SCMI_CLOCK_SET_PARENT_DENIED	BIT(13)
+#define SCMI_CLOCK_SET_RATE_DENIED	BIT(14)
+#define SCMI_CLOCK_SET_ENABLE_DENIED	BIT(15)
 struct scmi_clock_info {
 	char name[SCMI_MAX_STR_SIZE];
 	unsigned int enable_latency;
 	bool rate_discrete;
 	bool rate_changed_notifications;
 	bool rate_change_requested_notifications;
+	unsigned int flags;
 	union {
 		struct {
 			int num_rates;
-- 
2.37.1




More information about the linux-arm-kernel mailing list