]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
clk: clk-conf: support assigned-clock-rates-u64
authorPeng Fan <peng.fan@nxp.com>
Sun, 4 Aug 2024 12:32:56 +0000 (20:32 +0800)
committerStephen Boyd <sboyd@kernel.org>
Fri, 16 Aug 2024 22:21:19 +0000 (15:21 -0700)
i.MX95 System Management Control Firmware(SCMI) manages the clock
function, it exposes PLL VCO which could support up to 5GHz rate that
exceeds UINT32_MAX. So add assigned-clock-rates-u64 support
to set rate that exceeds UINT32_MAX.

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Link: https://lore.kernel.org/r/20240804-clk-u64-v4-2-8e55569f39a4@nxp.com
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/clk-conf.c

index 058420562020791865e69cfce3ee4771bab8cd93..303a0bb26e54a95655ce094a35b989c97ebc6fd8 100644 (file)
@@ -10,6 +10,7 @@
 #include <linux/device.h>
 #include <linux/of.h>
 #include <linux/printk.h>
+#include <linux/slab.h>
 
 static int __set_clk_parents(struct device_node *node, bool clk_supplier)
 {
@@ -81,11 +82,44 @@ err:
 static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 {
        struct of_phandle_args clkspec;
-       int rc, index = 0;
+       int rc, count, count_64, index;
        struct clk *clk;
-       u32 rate;
+       u64 *rates_64 __free(kfree) = NULL;
+       u32 *rates __free(kfree) = NULL;
+
+       count = of_property_count_u32_elems(node, "assigned-clock-rates");
+       count_64 = of_property_count_u64_elems(node, "assigned-clock-rates-u64");
+       if (count_64 > 0) {
+               count = count_64;
+               rates_64 = kcalloc(count, sizeof(*rates_64), GFP_KERNEL);
+               if (!rates_64)
+                       return -ENOMEM;
+
+               rc = of_property_read_u64_array(node,
+                                               "assigned-clock-rates-u64",
+                                               rates_64, count);
+       } else if (count > 0) {
+               rates = kcalloc(count, sizeof(*rates), GFP_KERNEL);
+               if (!rates)
+                       return -ENOMEM;
+
+               rc = of_property_read_u32_array(node, "assigned-clock-rates",
+                                               rates, count);
+       } else {
+               return 0;
+       }
+
+       if (rc)
+               return rc;
+
+       for (index = 0; index < count; index++) {
+               unsigned long rate;
+
+               if (rates_64)
+                       rate = rates_64[index];
+               else
+                       rate = rates[index];
 
-       of_property_for_each_u32(node, "assigned-clock-rates", rate) {
                if (rate) {
                        rc = of_parse_phandle_with_args(node, "assigned-clocks",
                                        "#clock-cells", index, &clkspec);
@@ -112,12 +146,11 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
 
                        rc = clk_set_rate(clk, rate);
                        if (rc < 0)
-                               pr_err("clk: couldn't set %s clk rate to %u (%d), current rate: %lu\n",
+                               pr_err("clk: couldn't set %s clk rate to %lu (%d), current rate: %lu\n",
                                       __clk_get_name(clk), rate, rc,
                                       clk_get_rate(clk));
                        clk_put(clk);
                }
-               index++;
        }
        return 0;
 }