On 3/21/25 8:15 AM, Alice Guo (OSS) wrote:

[...]

+static int scmi_clk_get_permissions(struct udevice *dev, int clkid, u32 *perm)
+{
+       u32 version;
+       int ret;
+
+       struct scmi_clk_get_permissions_in in = {
+               .clock_id = clkid,
+       };
+       struct scmi_clk_get_permissions_out out;
+       struct scmi_msg msg = {
+               .protocol_id = SCMI_PROTOCOL_ID_CLOCK,
+               .message_id = SCMI_CLOCK_GET_PERMISSIONS,
+               .in_msg = (u8 *)&in,
+               .in_msg_sz = sizeof(in),
+               .out_msg = (u8 *)&out,
+               .out_msg_sz = sizeof(out),
+       };
+
+       ret = scmi_generic_protocol_version(dev, SCMI_PROTOCOL_ID_CLOCK, 
&version);

Would it be possible to query the version in .probe() once and cache the value in private data ?

+       if (ret) {
+               log_debug("%s: get SCMI clock management protocol version 
failed\n", __func__);
+               return ret;
+       }
+
+       if (version < CLOCK_PROTOCOL_VERSION_3_0) {
+               log_debug("%s: SCMI clock management protocol version is less than 
3.0.\n", __func__);
+               return -EINVAL;
+       }
+
+       ret = devm_scmi_process_msg(dev, &msg);
+       if (ret) {
+               log_debug("%s: get SCMI clock management protocol permissions 
failed\n", __func__);
+               return ret;
+       }
+
+       ret = scmi_to_linux_errno(out.status);
+       if (ret < 0) {
+               log_debug("%s: the status code of getting permissions: %d\n", 
__func__, ret);
+               return ret;
+       }
+
+       *perm = out.permissions;
+       return 0;
+}

[...]

@@ -156,29 +267,44 @@ static int scmi_clk_probe(struct udevice *dev)
for (i = 0; i < num_clocks; i++) {
                char *clock_name;
+               u32 attributes;
- if (!scmi_clk_get_attibute(dev, i, &clock_name)) {
-                       clk = kzalloc(sizeof(*clk), GFP_KERNEL);
-                       if (!clk || !clock_name)
+               if (!scmi_clk_get_attibute(dev, i, &clock_name, &attributes)) {
+                       clk_scmi = kzalloc(sizeof(*clk_scmi), GFP_KERNEL);
+                       if (!clk_scmi || !clock_name)
                                ret = -ENOMEM;
                        else
-                               ret = clk_register(clk, dev->driver->name,
+                               ret = clk_register(&clk_scmi->clk, 
dev->driver->name,
                                                   clock_name, dev->name);
if (ret) {
-                               free(clk);
+                               free(clk_scmi);
                                free(clock_name);
+                               free(&attributes);

Do you really need to free() an u32 attributes here ?

                                return ret;
                        }
- clk_dm(i, clk);
+                       clk_dm(i, &clk_scmi->clk);
+
+                       if (CLK_HAS_RESTRICTIONS(attributes)) {
+                               u32 perm;
+
+                               ret = scmi_clk_get_permissions(dev, i, &perm);
+                               if (ret < 0)
+                                       clk_scmi->ctrl_flags = 0;
+                               else
+                                       clk_scmi->ctrl_flags = perm;
+                       } else {
+                               clk_scmi->ctrl_flags = SUPPORT_CLK_STAT_CONTROL 
| SUPPORT_CLK_PARENT_CONTROL |
+                                                      SUPPORT_CLK_RATE_CONTROL;
+                       }
                }
        }
return 0;
  }

[...]

  enum scmi_clock_message_id {
        SCMI_CLOCK_ATTRIBUTES = 0x3,
@@ -738,6 +739,7 @@ enum scmi_clock_message_id {
        SCMI_CLOCK_RATE_GET = 0x6,
        SCMI_CLOCK_CONFIG_SET = 0x7,
        SCMI_CLOCK_PARENT_SET = 0xD,
+       SCMI_CLOCK_GET_PERMISSIONS = 0xF,

Better call it SCMI_CLOCK_PERMISSIONS_GET to be consistent with the rest of these fields , unless this is some SCMI specification name ?

[...]

Reply via email to