aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch
diff options
context:
space:
mode:
authorÁlvaro Fernández Rojas <noltari@gmail.com>2022-05-16 23:40:32 +0200
committerÁlvaro Fernández Rojas <noltari@gmail.com>2022-05-17 15:11:22 +0200
commit20ea6adbf199097c4f5f591ffee088340630dae4 (patch)
treed6719d95e136611a1c25bbf7789652d6d402779d /target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch
parentbca05bd072180dc38ef740b37ded9572a6db1981 (diff)
downloadupstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.gz
upstream-20ea6adbf199097c4f5f591ffee088340630dae4.tar.bz2
upstream-20ea6adbf199097c4f5f591ffee088340630dae4.zip
bcm27xx: add support for linux v5.15
Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones <mj8263788@gmail.com> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
Diffstat (limited to 'target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch')
-rw-r--r--target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch196
1 files changed, 196 insertions, 0 deletions
diff --git a/target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch b/target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch
new file mode 100644
index 0000000000..b110f717ad
--- /dev/null
+++ b/target/linux/bcm27xx/patches-5.15/950-0834-clk-Always-set-the-rate-on-clk_set_range_rate.patch
@@ -0,0 +1,196 @@
+From c12b9d21ea40c608be608b83f803efdbdfe9657a Mon Sep 17 00:00:00 2001
+From: Maxime Ripard <maxime@cerno.tech>
+Date: Mon, 17 Jan 2022 16:43:13 +0100
+Subject: [PATCH] clk: Always set the rate on clk_set_range_rate
+
+When we change a clock minimum or maximum using clk_set_rate_range(),
+clk_set_min_rate() or clk_set_max_rate(), the current code will only
+trigger a new rate change if the rate is outside of the new boundaries.
+
+However, a clock driver might want to always keep the clock rate to
+one of its boundary, for example the minimum to keep the power
+consumption as low as possible.
+
+Since they don't always get called though, clock providers don't have the
+opportunity to implement this behaviour.
+
+Let's trigger a clk_set_rate() on the previous requested rate every time
+clk_set_rate_range() is called. That way, providers that care about the
+new boundaries have a chance to adjust the rate, while providers that
+don't care about those new boundaries will return the same rate than
+before, which will be ignored by clk_set_rate() and won't result in a
+new rate change.
+
+Suggested-by: Stephen Boyd <sboyd@kernel.org>
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+---
+ drivers/clk/clk.c | 45 ++++++++++++++++----------------
+ drivers/clk/clk_test.c | 58 +++++++++++++++++++-----------------------
+ 2 files changed, 49 insertions(+), 54 deletions(-)
+
+--- a/drivers/clk/clk.c
++++ b/drivers/clk/clk.c
+@@ -2372,28 +2372,29 @@ int clk_set_rate_range(struct clk *clk,
+ goto out;
+ }
+
+- rate = clk_core_get_rate_nolock(clk->core);
+- if (rate < min || rate > max) {
+- /*
+- * FIXME:
+- * We are in bit of trouble here, current rate is outside the
+- * the requested range. We are going try to request appropriate
+- * range boundary but there is a catch. It may fail for the
+- * usual reason (clock broken, clock protected, etc) but also
+- * because:
+- * - round_rate() was not favorable and fell on the wrong
+- * side of the boundary
+- * - the determine_rate() callback does not really check for
+- * this corner case when determining the rate
+- */
+-
+- rate = clamp(clk->core->req_rate, min, max);
+- ret = clk_core_set_rate_nolock(clk->core, rate);
+- if (ret) {
+- /* rollback the changes */
+- clk->min_rate = old_min;
+- clk->max_rate = old_max;
+- }
++ /*
++ * Since the boundaries have been changed, let's give the
++ * opportunity to the provider to adjust the clock rate based on
++ * the new boundaries.
++ *
++ * We also need to handle the case where the clock is currently
++ * outside of the boundaries. Clamping the last requested rate
++ * to the current minimum and maximum will also handle this.
++ *
++ * FIXME:
++ * There is a catch. It may fail for the usual reason (clock
++ * broken, clock protected, etc) but also because:
++ * - round_rate() was not favorable and fell on the wrong
++ * side of the boundary
++ * - the determine_rate() callback does not really check for
++ * this corner case when determining the rate
++ */
++ rate = clamp(clk->core->req_rate, min, max);
++ ret = clk_core_set_rate_nolock(clk->core, rate);
++ if (ret) {
++ /* rollback the changes */
++ clk->min_rate = old_min;
++ clk->max_rate = old_max;
+ }
+
+ out:
+--- a/drivers/clk/clk_test.c
++++ b/drivers/clk/clk_test.c
+@@ -549,13 +549,12 @@ static struct kunit_suite clk_range_test
+ };
+
+ /*
+- * Test that if:
+- * - we have several subsequent calls to clk_set_rate_range();
+- * - and we have a round_rate ops that always return the maximum
+- * frequency allowed;
++ * Test that if we have several subsequent calls to
++ * clk_set_rate_range(), the core will reevaluate whether a new rate is
++ * needed each and every time.
+ *
+- * The clock will run at the minimum of all maximum boundaries
+- * requested, even if those boundaries aren't there anymore.
++ * With clk_dummy_maximize_rate_ops, this means that the the rate will
++ * trail along the maximum as it evolves.
+ */
+ static void clk_range_test_set_range_rate_maximized(struct kunit *test)
+ {
+@@ -596,18 +595,16 @@ static void clk_range_test_set_range_rat
+
+ rate = clk_get_rate(clk);
+ KUNIT_ASSERT_GT(test, rate, 0);
+- KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2 - 1000);
++ KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
+ }
+
+ /*
+- * Test that if:
+- * - we have several subsequent calls to clk_set_rate_range(), across
+- * multiple users;
+- * - and we have a round_rate ops that always return the maximum
+- * frequency allowed;
++ * Test that if we have several subsequent calls to
++ * clk_set_rate_range(), across multiple users, the core will reevaluate
++ * whether a new rate is needed each and every time.
+ *
+- * The clock will run at the minimum of all maximum boundaries
+- * requested, even if those boundaries aren't there anymore.
++ * With clk_dummy_maximize_rate_ops, this means that the the rate will
++ * trail along the maximum as it evolves.
+ */
+ static void clk_range_test_multiple_set_range_rate_maximized(struct kunit *test)
+ {
+@@ -653,7 +650,7 @@ static void clk_range_test_multiple_set_
+
+ rate = clk_get_rate(clk);
+ KUNIT_ASSERT_GT(test, rate, 0);
+- KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
++ KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
+
+ clk_put(user2);
+ clk_put(user1);
+@@ -673,14 +670,13 @@ static struct kunit_suite clk_range_maxi
+ };
+
+ /*
+- * Test that if:
+- * - we have several subsequent calls to clk_set_rate_range()
+- * - and we have a round_rate ops that always return the minimum
+- * frequency allowed;
++ * Test that if we have several subsequent calls to
++ * clk_set_rate_range(), the core will reevaluate whether a new rate is
++ * needed each and every time.
+ *
+- * The clock will run at the maximum of all minimum boundaries
+- * requested, even if those boundaries aren't there anymore.
+-*/
++ * With clk_dummy_minimize_rate_ops, this means that the the rate will
++ * trail along the minimum as it evolves.
++ */
+ static void clk_range_test_set_range_rate_minimized(struct kunit *test)
+ {
+ struct clk_dummy_context *ctx = test->priv;
+@@ -720,19 +716,17 @@ static void clk_range_test_set_range_rat
+
+ rate = clk_get_rate(clk);
+ KUNIT_ASSERT_GT(test, rate, 0);
+- KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1 + 1000);
++ KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
+ }
+
+ /*
+- * Test that if:
+- * - we have several subsequent calls to clk_set_rate_range(), across
+- * multiple users;
+- * - and we have a round_rate ops that always return the minimum
+- * frequency allowed;
++ * Test that if we have several subsequent calls to
++ * clk_set_rate_range(), across multiple users, the core will reevaluate
++ * whether a new rate is needed each and every time.
+ *
+- * The clock will run at the maximum of all minimum boundaries
+- * requested, even if those boundaries aren't there anymore.
+-*/
++ * With clk_dummy_minimize_rate_ops, this means that the the rate will
++ * trail along the minimum as it evolves.
++ */
+ static void clk_range_test_multiple_set_range_rate_minimized(struct kunit *test)
+ {
+ struct clk_dummy_context *ctx = test->priv;
+@@ -773,7 +767,7 @@ static void clk_range_test_multiple_set_
+
+ rate = clk_get_rate(clk);
+ KUNIT_ASSERT_GT(test, rate, 0);
+- KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_2);
++ KUNIT_EXPECT_EQ(test, rate, DUMMY_CLOCK_RATE_1);
+
+ clk_put(user2);
+ clk_put(user1);