[PATCH v3 05/27] clk: add clk_round_rate()
Sean Anderson
seanga2 at gmail.com
Sun Oct 11 14:26:40 CEST 2020
On 10/11/20 8:13 AM, Dario Binacchi wrote:
> 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 at libero.it>
> Reviewed-by: Simon Glass <sjg at chromium.org>
>
> ---
>
> (no changes since v1)
>
> arch/sandbox/include/asm/clk.h | 9 +++++++++
> drivers/clk/clk-uclass.c | 15 +++++++++++++++
> drivers/clk/clk_sandbox.c | 17 +++++++++++++++++
> drivers/clk/clk_sandbox_test.c | 10 ++++++++++
> include/clk-uclass.h | 8 ++++++++
> include/clk.h | 29 +++++++++++++++++++++++++++++
> test/dm/clk.c | 22 ++++++++++++++++++++++
> 7 files changed, 110 insertions(+)
>
> diff --git a/arch/sandbox/include/asm/clk.h b/arch/sandbox/include/asm/clk.h
> index c184c4bffc..0294baee27 100644
> --- a/arch/sandbox/include/asm/clk.h
> +++ b/arch/sandbox/include/asm/clk.h
> @@ -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.
> diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
> index 31c5997aea..c16a8b120c 100644
> --- a/drivers/clk/clk-uclass.c
> +++ b/drivers/clk/clk-uclass.c
> @@ -524,6 +524,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;
> diff --git a/drivers/clk/clk_sandbox.c b/drivers/clk/clk_sandbox.c
> index 768fbb7c52..8361b930df 100644
> --- a/drivers/clk/clk_sandbox.c
> +++ b/drivers/clk/clk_sandbox.c
> @@ -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,
> diff --git a/drivers/clk/clk_sandbox_test.c b/drivers/clk/clk_sandbox_test.c
> index 873383856f..f7b77aa674 100644
> --- a/drivers/clk/clk_sandbox_test.c
> +++ b/drivers/clk/clk_sandbox_test.c
> @@ -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);
> diff --git a/include/clk-uclass.h b/include/clk-uclass.h
> index dac42dab36..50e8681b55 100644
> --- a/include/clk-uclass.h
> +++ b/include/clk-uclass.h
> @@ -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.
> *
> diff --git a/include/clk.h b/include/clk.h
> index a62e2efa2c..cce763b05b 100644
> --- a/include/clk.h
> +++ b/include/clk.h
> @@ -366,6 +366,30 @@ 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:
> + *
> + * clk_set_rate(clk, r);
> + * rate = clk_get_rate(clk);
Note that clk_set_rate returns the new rate on success, so the above is
equivalent to
rate = clk_set_rate(clk);
other than that,
Reviewed-by: Sean Anderson <seanga2 at gmail.com>
> + *
> + * 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 +506,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;
> diff --git a/test/dm/clk.c b/test/dm/clk.c
> index edca3b49f6..21997ed892 100644
> --- a/test/dm/clk.c
> +++ b/test/dm/clk.c
> @@ -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,
>
More information about the U-Boot
mailing list