]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
clk: add clk_round_rate()
authorDario Binacchi <dariobin@libero.it>
Tue, 29 Dec 2020 23:06:31 +0000 (00:06 +0100)
committerLokesh Vutla <lokeshvutla@ti.com>
Tue, 12 Jan 2021 05:28:04 +0000 (10:58 +0530)
It returns the rate which will be set if you ask clk_set_rate() to set
that rate. It provides a way to query exactly what rate you'll get if
you call clk_set_rate() with that same argument.
So essentially, clk_round_rate() and clk_set_rate() are equivalent
except the former does not modify the clock hardware in any way.

Signed-off-by: Dario Binacchi <dariobin@libero.it>
Reviewed-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Sean Anderson <seanga2@gmail.com>
arch/sandbox/include/asm/clk.h
drivers/clk/clk-uclass.c
drivers/clk/clk_sandbox.c
drivers/clk/clk_sandbox_test.c
include/clk-uclass.h
include/clk.h
test/dm/clk.c

index c184c4bffcf7b7ade69cc400bfa38119197994fc..0294baee278edde25a481ca3d3ed4b7cf25ec6fc 100644 (file)
@@ -105,6 +105,15 @@ int sandbox_clk_test_get_bulk(struct udevice *dev);
  * @return:    The rate of the clock.
  */
 ulong sandbox_clk_test_get_rate(struct udevice *dev, int id);
+/**
+ * sandbox_clk_test_round_rate - Ask the sandbox clock test device to round a
+ * clock's rate.
+ *
+ * @dev:       The sandbox clock test (client) device.
+ * @id:                The test device's clock ID to configure.
+ * @return:    The rounded rate of the clock.
+ */
+ulong sandbox_clk_test_round_rate(struct udevice *dev, int id, ulong rate);
 /**
  * sandbox_clk_test_set_rate - Ask the sandbox clock test device to set a
  * clock's rate.
index 5cfd00ce7710440fe377abd5af2624ce74d4457c..b75056718bf4fb06c08e0816bc6f955dba79a8af 100644 (file)
@@ -523,6 +523,21 @@ long long clk_get_parent_rate(struct clk *clk)
        return pclk->rate;
 }
 
+ulong clk_round_rate(struct clk *clk, ulong rate)
+{
+       const struct clk_ops *ops;
+
+       debug("%s(clk=%p, rate=%lu)\n", __func__, clk, rate);
+       if (!clk_valid(clk))
+               return 0;
+
+       ops = clk_dev_ops(clk->dev);
+       if (!ops->round_rate)
+               return -ENOSYS;
+
+       return ops->round_rate(clk, rate);
+}
+
 ulong clk_set_rate(struct clk *clk, ulong rate)
 {
        const struct clk_ops *ops;
index 2c6c0e239f7e7949cd01280ef873121b072ac570..b28b67b44860020c287182d9afb50ceb37132993 100644 (file)
@@ -30,6 +30,22 @@ static ulong sandbox_clk_get_rate(struct clk *clk)
        return priv->rate[clk->id];
 }
 
+static ulong sandbox_clk_round_rate(struct clk *clk, ulong rate)
+{
+       struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
+
+       if (!priv->probed)
+               return -ENODEV;
+
+       if (clk->id >= SANDBOX_CLK_ID_COUNT)
+               return -EINVAL;
+
+       if (!rate)
+               return -EINVAL;
+
+       return rate;
+}
+
 static ulong sandbox_clk_set_rate(struct clk *clk, ulong rate)
 {
        struct sandbox_clk_priv *priv = dev_get_priv(clk->dev);
@@ -103,6 +119,7 @@ static int sandbox_clk_free(struct clk *clk)
 }
 
 static struct clk_ops sandbox_clk_ops = {
+       .round_rate     = sandbox_clk_round_rate,
        .get_rate       = sandbox_clk_get_rate,
        .set_rate       = sandbox_clk_set_rate,
        .enable         = sandbox_clk_enable,
index e9eb738684b82013d853f8af493913be03706898..c4e448150846d3205eab04d0a3e52e2dbb20c4e8 100644 (file)
@@ -86,6 +86,16 @@ ulong sandbox_clk_test_get_rate(struct udevice *dev, int id)
        return clk_get_rate(sbct->clkps[id]);
 }
 
+ulong sandbox_clk_test_round_rate(struct udevice *dev, int id, ulong rate)
+{
+       struct sandbox_clk_test *sbct = dev_get_priv(dev);
+
+       if (id < 0 || id >= SANDBOX_CLK_TEST_ID_COUNT)
+               return -EINVAL;
+
+       return clk_round_rate(sbct->clkps[id], rate);
+}
+
 ulong sandbox_clk_test_set_rate(struct udevice *dev, int id, ulong rate)
 {
        struct sandbox_clk_test *sbct = dev_get_priv(dev);
index dac42dab3681287bbe777a2effea7a25f5a1dfbf..50e8681b553fade5b12de56294c1af81bc31133c 100644 (file)
@@ -61,6 +61,14 @@ struct clk_ops {
         * @return 0 if OK, or a negative error code.
         */
        int (*rfree)(struct clk *clock);
+       /**
+        * round_rate() - Adjust a rate to the exact rate a clock can provide.
+        *
+        * @clk:        The clock to manipulate.
+        * @rate:       Desidered clock rate in Hz.
+        * @return rounded rate in Hz, or -ve error code.
+        */
+       ulong (*round_rate)(struct clk *clk, ulong rate);
        /**
         * get_rate() - Get current clock rate.
         *
index a62e2efa2ca45f23b4abd0718c581216a7c7d940..ca6b85fa6fe506a294b5cf23435b20225a8e501e 100644 (file)
@@ -366,6 +366,29 @@ struct clk *clk_get_parent(struct clk *clk);
  */
 long long clk_get_parent_rate(struct clk *clk);
 
+/**
+ * clk_round_rate() - Adjust a rate to the exact rate a clock can provide
+ *
+ * This answers the question "if I were to pass @rate to clk_set_rate(),
+ * what clock rate would I end up with?" without changing the hardware
+ * in any way.  In other words:
+ *
+ *   rate = clk_round_rate(clk, r);
+ *
+ * and:
+ *
+ *   rate = clk_set_rate(clk, r);
+ *
+ * are equivalent except the former does not modify the clock hardware
+ * in any way.
+ *
+ * @clk: A clock struct that was previously successfully requested by
+ *       clk_request/get_by_*().
+ * @rate: desired clock rate in Hz.
+ * @return rounded rate in Hz, or -ve error code.
+ */
+ulong clk_round_rate(struct clk *clk, ulong rate);
+
 /**
  * clk_set_rate() - Set current clock rate.
  *
@@ -482,6 +505,11 @@ static inline long long clk_get_parent_rate(struct clk *clk)
        return -ENOSYS;
 }
 
+static inline ulong clk_round_rate(struct clk *clk, ulong rate)
+{
+       return -ENOSYS;
+}
+
 static inline ulong clk_set_rate(struct clk *clk, ulong rate)
 {
        return -ENOSYS;
index edca3b49f6001ce94cd1f60ed142acfdf54defd6..21997ed892290dc11ed7eb6cb737cfb6aa6b5432 100644 (file)
@@ -112,6 +112,28 @@ static int dm_test_clk(struct unit_test_state *uts)
        rate = sandbox_clk_test_set_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0);
        ut_assert(IS_ERR_VALUE(rate));
 
+       ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test,
+                                                    SANDBOX_CLK_TEST_ID_SPI));
+       ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test,
+                                                    SANDBOX_CLK_TEST_ID_I2C));
+
+       ut_asserteq(5000, sandbox_clk_test_round_rate(dev_test,
+                                                     SANDBOX_CLK_TEST_ID_SPI,
+                                                     5000));
+       ut_asserteq(7000, sandbox_clk_test_round_rate(dev_test,
+                                                     SANDBOX_CLK_TEST_ID_I2C,
+                                                     7000));
+
+       ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test,
+                                                    SANDBOX_CLK_TEST_ID_SPI));
+       ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test,
+                                                    SANDBOX_CLK_TEST_ID_I2C));
+
+       rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_SPI, 0);
+       ut_assert(IS_ERR_VALUE(rate));
+       rate = sandbox_clk_test_round_rate(dev_test, SANDBOX_CLK_TEST_ID_I2C, 0);
+       ut_assert(IS_ERR_VALUE(rate));
+
        ut_asserteq(10000, sandbox_clk_test_get_rate(dev_test,
                                                     SANDBOX_CLK_TEST_ID_SPI));
        ut_asserteq(20000, sandbox_clk_test_get_rate(dev_test,