clk: add clk_round_rate()

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>
diff --git a/drivers/clk/clk-uclass.c b/drivers/clk/clk-uclass.c
index 5cfd00c..b750567 100644
--- a/drivers/clk/clk-uclass.c
+++ b/drivers/clk/clk-uclass.c
@@ -523,6 +523,21 @@
 	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 2c6c0e2..b28b67b 100644
--- a/drivers/clk/clk_sandbox.c
+++ b/drivers/clk/clk_sandbox.c
@@ -30,6 +30,22 @@
 	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 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 e9eb738..c4e4481 100644
--- a/drivers/clk/clk_sandbox_test.c
+++ b/drivers/clk/clk_sandbox_test.c
@@ -86,6 +86,16 @@
 	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);