linux-sunxi.lists.linux.dev archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate
@ 2023-08-07 12:43 Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 01/11] clk: sunxi-ng: nkm: Use correct parameter name for parent HW Frank Oltmanns
                   ` (11 more replies)
  0 siblings, 12 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

This patchset enables NKM clocks to consider alternative parent rates
and utilize this new feature to adjust the pll-video0 clock on Allwinner
A64.

Furthermore, with this patchset pll-video0 considers rates that are
higher than the requested rate when finding the closest rate. In
consequence, higher rates are also considered by pll-video0's
descandents. In total, after applying this patchset, finding the closest
rate is supported by:
  - ccu_nm
  - ccu_nkm
  - ccu_mux
  - ccu_div

This allows us to achieve an optimal rate for driving the board's panel.

To provide some context, the clock structure involved in this process is
as follows:
    clock                       clock type
    --------------------------------------
    pll-video0                  ccu_nm
       pll-mipi                 ccu_nkm
          tcon0                 ccu_mux
             tcon-data-clock    sun4i_dclk

The divider between tcon0 and tcon-data-clock is fixed at 4. Therefore,
in order to achieve a rate that closely matches the desired rate of the
panel, pll-mipi needs to operate at a specific rate.

Tests
=====
So far, this has been successfully tested on the A64-based Pinephone
using three different panel rates:

 1. A panel rate that can be matched exactly by pll-video0.
 2. A panel rate that requires pll-video0 to undershoot to get the
    closest rate.
 3. A panel rate that requires pll-video0 to overshoot to get the
    closest rate.

Test records:

Re 1:
-----
Panel requests tcon-data-clock of 103500000 Hz, i.e., pll-mipi needs to
run at 414000000 Hz. This results in the following clock rates:
   clock                            rate
   -------------------------------------
    pll-video0                 207000000
       hdmi-phy-clk             51750000
       hdmi                    207000000
       tcon1                   207000000
       pll-mipi                414000000
          tcon0                414000000
             tcon-data-clock   103500000

The results of the find_best calls:
ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
ccu_nkm_find_best: rate=414000000, best_rate=414000000, parent_rate=207000000, n=1, k=2, m=1

Re 2:
-----
Panel requests tcon-data-clock of 103650000 Hz, i.e., pll-mipi needs to
run at 414600000 Hz. This results in the following clock rates:
   clock                            rate
   -------------------------------------
    pll-video0                 282666666
       hdmi-phy-clk             70666666
       hdmi                    282666666
       tcon1                   282666666
       pll-mipi                414577776
          tcon0                414577776
             tcon-data-clock   103644444

The results of the find_best calls:
ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
ccu_nkm_find_best: rate=414577776, best_rate=414577776, parent_rate=282666666, n=11, k=2, m=15

Re 3:
-----
Panel requests tcon-data-clock of 112266000 Hz, i.e., pll-mipi needs to
run at 449064000 Hz. This results in the following clock rates:
   clock                            rate
   -------------------------------------
    pll-video0                 207272727
       hdmi-phy-clk             51818181
       hdmi                    207272727
       tcon1                   207272727
       pll-mipi                449090908
          tcon0                449090908
             tcon-data-clock   112272727

The results of the find_best calls:
ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
ccu_nkm_find_best: rate=449090908, best_rate=449090908, parent_rate=207272727, n=13, k=2, m=12

Changelog:
----------
Changes in v6:
 - Removed unnecessary #include from ccu_nkm.c
 - Link to v5: https://lore.kernel.org/r/20230806-pll-mipi_set_rate_parent-v5-0-db4f5ca33fc3@oltmanns.dev

Changes in v5:
 - Remove the dedicated function for calculating the optimal parent rate
   for nkm clocks that was introduced in v2 and again in v4. Instead use
   a simple calculation and require the parent clock to select the
   closest rate to achieve optimal results.
 - Change the order of parameters of nkm_best_rate and
   nkm_best_rate_with_parent_adj as requested my Maxime Ripard.
 - Prefer to not reset the rate of the nkm clock's parent if the ideal
   rate can be reached using the parent's current rate, copying the
   behavior of ccu_mp.
 - Link to v4: https://lore.kernel.org/r/20230717-pll-mipi_set_rate_parent-v4-0-04acf1d39765@oltmanns.dev

Changes in v4:
 - Re-introduce a dedicated function for calculating the optimal parent
   rate for nkm clocks that was introduced in v2 and removed in v3. It
   turned out that not having this functionality introduces a bug when
   the parent does not support finding the closest rate:
   https://lore.kernel.org/all/87pm4xg2ub.fsf@oltmanns.dev/
 - Incorporate review remarks:
    - Correcting the parameter name for ccu_nkm_round_rate()'s parent HW
      is now in a separate patch.
    - Use correct parameter order in ccu_nkm_find_best_with_parent_adj.
    - Add ccu_is_better_rate() and use it for determining the best rate
      for nm and nkm, as well as ccu_mux_helper_determine_rate.
    - Consistently introduce new macros for clock variants that support
      finding the closest rate instead of updating existing macros.
    - Use wrapper function for determining a ccu_mux's rate in order to
      support finding the closest rate.
 - Link to v3: https://lore.kernel.org/r/20230702-pll-mipi_set_rate_parent-v3-0-46dcb8aa9cbc@oltmanns.dev

Changes in v3:
 - Use dedicated function for finding the best rate in cases where an
   nkm clock supports setting its parent's rate, streamlining it with
   the structure that is used in other sunxi-ng ccus such as ccu_mp
   (PATCH 1).
 - Therefore, remove the now obsolete comments that were introduced in
   v2 (PATCH 1).
 - Remove the dedicated function for calculating the optimal parent rate
   for nkm clocks that was introduced in v2. Instead use a simple
   calculation and require the parent clock to select the closest rate to
   achieve optimal results (PATCH 1).
 - Therefore, add support to set the closest rate for nm clocks (because
   pll-mipi's parent pll-video0 is an nm clock) and all clock types that
   are descendants of a64's pll-video0, i.e., nkm, mux, and div (PATCH 3
   et. seq.).
 - Link to v2: https://lore.kernel.org/all/20230611090143.132257-1-frank@oltmanns.dev/

Changes in V2:
 - Move optimal parent rate calculation to dedicated function
 - Choose a parent rate that does not to overshoot requested rate
 - Add comments to ccu_nkm_find_best
 - Make sure that best_parent_rate stays at original parent rate in the unlikely
   case that all combinations overshoot.

Link to V1:
https://lore.kernel.org/lkml/20230605190745.366882-1-frank@oltmanns.dev/

---
Frank Oltmanns (11):
      clk: sunxi-ng: nkm: Use correct parameter name for parent HW
      clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
      clk: sunxi-ng: a64: allow pll-mipi to set parent's rate
      clk: sunxi-ng: Add feature to find closest rate
      clk: sunxi-ng: Add helper function to find closest rate
      clk: sunxi-ng: nm: Support finding closest rate
      clk: sunxi-ng: nkm: Support finding closest rate
      clk: sunxi-ng: mux: Support finding closest rate
      clk: sunxi-ng: div: Support finding closest rate
      clk: sunxi-ng: a64: select closest rate for pll-video0
      clk: sunxi-ng: nkm: Prefer current parent rate

 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 36 ++++++++++-------------
 drivers/clk/sunxi-ng/ccu_common.c     | 12 ++++++++
 drivers/clk/sunxi-ng/ccu_common.h     |  6 ++++
 drivers/clk/sunxi-ng/ccu_div.h        | 30 +++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_mux.c        | 15 ++++++++--
 drivers/clk/sunxi-ng/ccu_mux.h        | 38 +++++++++++++++++-------
 drivers/clk/sunxi-ng/ccu_nkm.c        | 55 ++++++++++++++++++++++++++++++-----
 drivers/clk/sunxi-ng/ccu_nm.c         | 13 ++++-----
 drivers/clk/sunxi-ng/ccu_nm.h         | 48 ++++++++++++++++++++++++++++--
 9 files changed, 202 insertions(+), 51 deletions(-)
---
base-commit: 6995e2de6891c724bfeb2db33d7b87775f913ad1
change-id: 20230626-pll-mipi_set_rate_parent-3363fc0d6e6f

Best regards,
-- 
Frank Oltmanns <frank@oltmanns.dev>


^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v6 01/11] clk: sunxi-ng: nkm: Use correct parameter name for parent HW
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate Frank Oltmanns
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

ccu_nkm_round_rate() takes a clk_hw as parameter "hw". Since "hw" is the
nkm clock's parent clk_hw, not the clk_hw of the nkm clock itself,
change the parameter name to "parent_hw" to make it more clear what
we're dealing with.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index a0978a50edae..f267142e58b3 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -106,7 +106,7 @@ static unsigned long ccu_nkm_recalc_rate(struct clk_hw *hw,
 }
 
 static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
-					struct clk_hw *hw,
+					struct clk_hw *parent_hw,
 					unsigned long *parent_rate,
 					unsigned long rate,
 					void *data)

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 01/11] clk: sunxi-ng: nkm: Use correct parameter name for parent HW Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 14:28   ` Chen-Yu Tsai
  2023-08-07 12:43 ` [PATCH v6 03/11] clk: sunxi-ng: a64: allow pll-mipi to set parent's rate Frank Oltmanns
                   ` (9 subsequent siblings)
  11 siblings, 1 reply; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

In case the CLK_SET_RATE_PARENT flag is set, consider using a different
parent rate when determining a new rate.

To find the best match for the requested rate, perform the following
steps for each NKM combination:
 - calculate the optimal parent rate,
 - find the best parent rate that the parent clock actually supports
 - use that parent rate to calculate the effective rate.

In case the clk does not support setting the parent rate, use the same
algorithm as before.

Acked-by: Maxime Ripard <mripard@kernel.org>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 44 +++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index f267142e58b3..2f60f3c33e30 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,6 +16,45 @@ struct _ccu_nkm {
 	unsigned long	m, min_m, max_m;
 };
 
+static unsigned long ccu_nkm_find_best_with_parent_adj(struct clk_hw *parent_hw,
+						       unsigned long *parent, unsigned long rate,
+						       struct _ccu_nkm *nkm)
+{
+	unsigned long best_rate = 0, best_parent_rate = *parent, tmp_parent = *parent;
+	unsigned long best_n = 0, best_k = 0, best_m = 0;
+	unsigned long _n, _k, _m;
+
+	for (_k = nkm->min_k; _k <= nkm->max_k; _k++) {
+		for (_n = nkm->min_n; _n <= nkm->max_n; _n++) {
+			for (_m = nkm->min_m; _m <= nkm->max_m; _m++) {
+				unsigned long tmp_rate;
+
+				tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k));
+
+				tmp_rate = tmp_parent * _n * _k / _m;
+				if (tmp_rate > rate)
+					continue;
+
+				if ((rate - tmp_rate) < (rate - best_rate)) {
+					best_rate = tmp_rate;
+					best_parent_rate = tmp_parent;
+					best_n = _n;
+					best_k = _k;
+					best_m = _m;
+				}
+			}
+		}
+	}
+
+	nkm->n = best_n;
+	nkm->k = best_k;
+	nkm->m = best_m;
+
+	*parent = best_parent_rate;
+
+	return best_rate;
+}
+
 static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
 				       struct _ccu_nkm *nkm)
 {
@@ -124,7 +163,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
 	if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate *= nkm->fixed_post_div;
 
-	rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm);
+	if (!clk_hw_can_set_rate_parent(&nkm->common.hw))
+		rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm);
+	else
+		rate = ccu_nkm_find_best_with_parent_adj(parent_hw, parent_rate, rate, &_nkm);
 
 	if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate /= nkm->fixed_post_div;

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 03/11] clk: sunxi-ng: a64: allow pll-mipi to set parent's rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 01/11] clk: sunxi-ng: nkm: Use correct parameter name for parent HW Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 04/11] clk: sunxi-ng: Add feature to find closest rate Frank Oltmanns
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

The nkm clock now supports setting the parent's rate. Utilize this
option to find the optimal rate for pll-mipi.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 41519185600a..a139a5c438d4 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -179,7 +179,8 @@ static struct ccu_nkm pll_mipi_clk = {
 	.common		= {
 		.reg		= 0x040,
 		.hw.init	= CLK_HW_INIT("pll-mipi", "pll-video0",
-					      &ccu_nkm_ops, CLK_SET_RATE_UNGATE),
+					      &ccu_nkm_ops,
+					      CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
 	},
 };
 

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 04/11] clk: sunxi-ng: Add feature to find closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (2 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 03/11] clk: sunxi-ng: a64: allow pll-mipi to set parent's rate Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 05/11] clk: sunxi-ng: Add helper function " Frank Oltmanns
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

The default behaviour of clocks in the sunxi-ng driver is to select a
clock rate that is closest to but less than the requested rate.

Add the CCU_FEATURE_CLOSEST_RATE flag, which can be used to allow clocks
to find the closest rate instead.

Acked-by: Maxime Ripard <mripard@kernel.org>
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_common.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index fbf16c6b896d..5ad219f041d5 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -18,6 +18,7 @@
 #define CCU_FEATURE_MMC_TIMING_SWITCH	BIT(6)
 #define CCU_FEATURE_SIGMA_DELTA_MOD	BIT(7)
 #define CCU_FEATURE_KEY_FIELD		BIT(8)
+#define CCU_FEATURE_CLOSEST_RATE	BIT(9)
 
 /* MMC timing mode switch bit */
 #define CCU_MMC_NEW_TIMING_MODE		BIT(30)

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 05/11] clk: sunxi-ng: Add helper function to find closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (3 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 04/11] clk: sunxi-ng: Add feature to find closest rate Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 06/11] clk: sunxi-ng: nm: Support finding " Frank Oltmanns
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

The default behaviour of clocks in the sunxi-ng driver is to select a
clock rate that is closest to but less than the requested rate.

Add the ccu_is_better_rate() helper function that - depending on the
fact if thc CCU_FEATURE_CLOSEST_RATE flag is set - decides if a rate is
closer than another rate.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_common.c | 12 ++++++++++++
 drivers/clk/sunxi-ng/ccu_common.h |  5 +++++
 2 files changed, 17 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
index 8d28a7a079d0..8babce55302f 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -39,6 +39,18 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
 }
 EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU);
 
+bool ccu_is_better_rate(struct ccu_common *common,
+			unsigned long target_rate,
+			unsigned long current_rate,
+			unsigned long best_rate)
+{
+	if (common->features & CCU_FEATURE_CLOSEST_RATE)
+		return abs(current_rate - target_rate) < abs(best_rate - target_rate);
+
+	return current_rate <= target_rate && current_rate > best_rate;
+}
+EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, SUNXI_CCU);
+
 /*
  * This clock notifier is called when the frequency of a PLL clock is
  * changed. In common PLL designs, changes to the dividers take effect
diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 5ad219f041d5..942a72c09437 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -53,6 +53,11 @@ struct sunxi_ccu_desc {
 
 void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock);
 
+bool ccu_is_better_rate(struct ccu_common *common,
+			unsigned long target_rate,
+			unsigned long current_rate,
+			unsigned long best_rate);
+
 struct ccu_pll_nb {
 	struct notifier_block	clk_nb;
 	struct ccu_common	*common;

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 06/11] clk: sunxi-ng: nm: Support finding closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (4 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 05/11] clk: sunxi-ng: Add helper function " Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 07/11] clk: sunxi-ng: nkm: " Frank Oltmanns
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

Use the helper function ccu_is_better_rate() to determine the rate that
is closest to the requested rate, thereby supporting rates that are
higher than the requested rate if the clock uses the
CCU_FEATURE_CLOSEST_RATE.

Add the macro SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST which
sets CCU_FEATURE_CLOSEST_RATE.

To avoid code duplication, add the macros
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT that allows selecting
arbitrary features and use it in the original
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX as well as the newly introduced
SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST macros.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_nm.c | 13 +++++-------
 drivers/clk/sunxi-ng/ccu_nm.h | 48 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index c1fd11542c45..ffac3deb89d6 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -27,8 +27,8 @@ static unsigned long ccu_nm_calc_rate(unsigned long parent,
 	return rate;
 }
 
-static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate,
-				      struct _ccu_nm *nm)
+static unsigned long ccu_nm_find_best(struct ccu_common *common, unsigned long parent,
+				      unsigned long rate, struct _ccu_nm *nm)
 {
 	unsigned long best_rate = 0;
 	unsigned long best_n = 0, best_m = 0;
@@ -39,10 +39,7 @@ static unsigned long ccu_nm_find_best(unsigned long parent, unsigned long rate,
 			unsigned long tmp_rate = ccu_nm_calc_rate(parent,
 								  _n, _m);
 
-			if (tmp_rate > rate)
-				continue;
-
-			if ((rate - tmp_rate) < (rate - best_rate)) {
+			if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
 				best_rate = tmp_rate;
 				best_n = _n;
 				best_m = _m;
@@ -159,7 +156,7 @@ static long ccu_nm_round_rate(struct clk_hw *hw, unsigned long rate,
 	_nm.min_m = 1;
 	_nm.max_m = nm->m.max ?: 1 << nm->m.width;
 
-	rate = ccu_nm_find_best(*parent_rate, rate, &_nm);
+	rate = ccu_nm_find_best(&nm->common, *parent_rate, rate, &_nm);
 
 	if (nm->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate /= nm->fixed_post_div;
@@ -210,7 +207,7 @@ static int ccu_nm_set_rate(struct clk_hw *hw, unsigned long rate,
 					   &_nm.m, &_nm.n);
 	} else {
 		ccu_sdm_helper_disable(&nm->common, &nm->sdm);
-		ccu_nm_find_best(parent_rate, rate, &_nm);
+		ccu_nm_find_best(&nm->common, parent_rate, rate, &_nm);
 	}
 
 	spin_lock_irqsave(nm->common.lock, flags);
diff --git a/drivers/clk/sunxi-ng/ccu_nm.h b/drivers/clk/sunxi-ng/ccu_nm.h
index 2904e67f05a8..93c11693574f 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.h
+++ b/drivers/clk/sunxi-ng/ccu_nm.h
@@ -108,7 +108,7 @@ struct ccu_nm {
 		},							\
 	}
 
-#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name,	\
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name,	\
 						 _parent, _reg,		\
 						 _min_rate, _max_rate,	\
 						 _nshift, _nwidth,	\
@@ -116,7 +116,8 @@ struct ccu_nm {
 						 _frac_en, _frac_sel,	\
 						 _frac_rate_0,		\
 						 _frac_rate_1,		\
-						 _gate, _lock, _flags)	\
+						 _gate, _lock, _flags,	\
+						 _features)		\
 	struct ccu_nm _struct = {					\
 		.enable		= _gate,				\
 		.lock		= _lock,				\
@@ -129,7 +130,7 @@ struct ccu_nm {
 		.max_rate	= _max_rate,				\
 		.common		= {					\
 			.reg		= _reg,				\
-			.features	= CCU_FEATURE_FRACTIONAL,	\
+			.features	= _features,			\
 			.hw.init	= CLK_HW_INIT(_name,		\
 						      _parent,		\
 						      &ccu_nm_ops,	\
@@ -137,6 +138,47 @@ struct ccu_nm {
 		},							\
 	}
 
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(_struct, _name,	\
+						 _parent, _reg,		\
+						 _min_rate, _max_rate,	\
+						 _nshift, _nwidth,	\
+						 _mshift, _mwidth,	\
+						 _frac_en, _frac_sel,	\
+						 _frac_rate_0,		\
+						 _frac_rate_1,		\
+						 _gate, _lock, _flags)	\
+	SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name,	\
+						_parent, _reg,		\
+						_min_rate, _max_rate,	\
+						_nshift, _nwidth,	\
+						_mshift, _mwidth,	\
+						_frac_en, _frac_sel,	\
+						_frac_rate_0,		\
+						_frac_rate_1,		\
+						_gate, _lock, _flags,	\
+						CCU_FEATURE_FRACTIONAL)
+
+#define SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(_struct, _name, \
+						 _parent, _reg,		\
+						 _min_rate, _max_rate,	\
+						 _nshift, _nwidth,	\
+						 _mshift, _mwidth,	\
+						 _frac_en, _frac_sel,	\
+						 _frac_rate_0,		\
+						 _frac_rate_1,		\
+						 _gate, _lock, _flags)	\
+	SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_FEAT(_struct, _name,	\
+						_parent, _reg,		\
+						_min_rate, _max_rate,	\
+						_nshift, _nwidth,	\
+						_mshift, _mwidth,	\
+						_frac_en, _frac_sel,	\
+						_frac_rate_0,		\
+						_frac_rate_1,		\
+						_gate, _lock, _flags,	\
+						CCU_FEATURE_FRACTIONAL |\
+						CCU_FEATURE_CLOSEST_RATE)
+
 #define SUNXI_CCU_NM_WITH_GATE_LOCK(_struct, _name, _parent, _reg,	\
 				    _nshift, _nwidth,			\
 				    _mshift, _mwidth,			\

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 07/11] clk: sunxi-ng: nkm: Support finding closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (5 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 06/11] clk: sunxi-ng: nm: Support finding " Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 08/11] clk: sunxi-ng: mux: " Frank Oltmanns
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

When finding the best rate for a NKM clock, consider rates that are
higher than the requested rate, if the CCU_FEATURE_CLOSEST_RATE flag is
set by using the helper function ccu_is_better_rate().

Accommodate ccu_mux_helper_determine_rate to this change.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_mux.c |  2 +-
 drivers/clk/sunxi-ng/ccu_nkm.c | 20 +++++++++-----------
 2 files changed, 10 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 1d557e323169..3ca695439620 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -139,7 +139,7 @@ int ccu_mux_helper_determine_rate(struct ccu_common *common,
 			goto out;
 		}
 
-		if ((req->rate - tmp_rate) < (req->rate - best_rate)) {
+		if (ccu_is_better_rate(common, req->rate, tmp_rate, best_rate)) {
 			best_rate = tmp_rate;
 			best_parent_rate = parent_rate;
 			best_parent = parent;
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 2f60f3c33e30..a714dcf0dfc1 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -16,7 +16,8 @@ struct _ccu_nkm {
 	unsigned long	m, min_m, max_m;
 };
 
-static unsigned long ccu_nkm_find_best_with_parent_adj(struct clk_hw *parent_hw,
+static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common,
+						       struct clk_hw *parent_hw,
 						       unsigned long *parent, unsigned long rate,
 						       struct _ccu_nkm *nkm)
 {
@@ -32,10 +33,8 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct clk_hw *parent_hw,
 				tmp_parent = clk_hw_round_rate(parent_hw, rate * _m / (_n * _k));
 
 				tmp_rate = tmp_parent * _n * _k / _m;
-				if (tmp_rate > rate)
-					continue;
 
-				if ((rate - tmp_rate) < (rate - best_rate)) {
+				if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
 					best_rate = tmp_rate;
 					best_parent_rate = tmp_parent;
 					best_n = _n;
@@ -56,7 +55,7 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct clk_hw *parent_hw,
 }
 
 static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
-				       struct _ccu_nkm *nkm)
+				       struct _ccu_nkm *nkm, struct ccu_common *common)
 {
 	unsigned long best_rate = 0;
 	unsigned long best_n = 0, best_k = 0, best_m = 0;
@@ -69,9 +68,7 @@ static unsigned long ccu_nkm_find_best(unsigned long parent, unsigned long rate,
 
 				tmp_rate = parent * _n * _k / _m;
 
-				if (tmp_rate > rate)
-					continue;
-				if ((rate - tmp_rate) < (rate - best_rate)) {
+				if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
 					best_rate = tmp_rate;
 					best_n = _n;
 					best_k = _k;
@@ -164,9 +161,10 @@ static unsigned long ccu_nkm_round_rate(struct ccu_mux_internal *mux,
 		rate *= nkm->fixed_post_div;
 
 	if (!clk_hw_can_set_rate_parent(&nkm->common.hw))
-		rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm);
+		rate = ccu_nkm_find_best(*parent_rate, rate, &_nkm, &nkm->common);
 	else
-		rate = ccu_nkm_find_best_with_parent_adj(parent_hw, parent_rate, rate, &_nkm);
+		rate = ccu_nkm_find_best_with_parent_adj(&nkm->common, parent_hw, parent_rate, rate,
+							 &_nkm);
 
 	if (nkm->common.features & CCU_FEATURE_FIXED_POSTDIV)
 		rate /= nkm->fixed_post_div;
@@ -201,7 +199,7 @@ static int ccu_nkm_set_rate(struct clk_hw *hw, unsigned long rate,
 	_nkm.min_m = 1;
 	_nkm.max_m = nkm->m.max ?: 1 << nkm->m.width;
 
-	ccu_nkm_find_best(parent_rate, rate, &_nkm);
+	ccu_nkm_find_best(parent_rate, rate, &_nkm, &nkm->common);
 
 	spin_lock_irqsave(nkm->common.lock, flags);
 

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 08/11] clk: sunxi-ng: mux: Support finding closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (6 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 07/11] clk: sunxi-ng: nkm: " Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 09/11] clk: sunxi-ng: div: " Frank Oltmanns
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

When finding the best rate for a mux clock, consider rates that are
higher than the requested rate when CCU_FEATURE_ROUND_CLOSEST is used.
Furthermore, introduce an initialization macro that sets this flag.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_mux.c | 13 ++++++++++++-
 drivers/clk/sunxi-ng/ccu_mux.h | 38 +++++++++++++++++++++++++++-----------
 2 files changed, 39 insertions(+), 12 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 3ca695439620..5edc63b46651 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -242,6 +242,17 @@ static int ccu_mux_set_parent(struct clk_hw *hw, u8 index)
 	return ccu_mux_helper_set_parent(&cm->common, &cm->mux, index);
 }
 
+static int ccu_mux_determine_rate(struct clk_hw *hw,
+				  struct clk_rate_request *req)
+{
+	struct ccu_mux *cm = hw_to_ccu_mux(hw);
+
+	if (cm->common.features & CCU_FEATURE_CLOSEST_RATE)
+		return clk_mux_determine_rate_flags(hw, req, CLK_MUX_ROUND_CLOSEST);
+
+	return clk_mux_determine_rate_flags(hw, req, 0);
+}
+
 static unsigned long ccu_mux_recalc_rate(struct clk_hw *hw,
 					 unsigned long parent_rate)
 {
@@ -259,7 +270,7 @@ const struct clk_ops ccu_mux_ops = {
 	.get_parent	= ccu_mux_get_parent,
 	.set_parent	= ccu_mux_set_parent,
 
-	.determine_rate	= __clk_mux_determine_rate,
+	.determine_rate	= ccu_mux_determine_rate,
 	.recalc_rate	= ccu_mux_recalc_rate,
 };
 EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h
index 2c1811a445b0..eb1172ebbd94 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.h
+++ b/drivers/clk/sunxi-ng/ccu_mux.h
@@ -46,20 +46,36 @@ struct ccu_mux {
 	struct ccu_common	common;
 };
 
+#define SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents, _table,	\
+				     _reg, _shift, _width, _gate,		\
+				     _flags, _features)				\
+	struct ccu_mux _struct = {						\
+		.enable	= _gate,						\
+		.mux	= _SUNXI_CCU_MUX_TABLE(_shift, _width, _table),		\
+		.common	= {							\
+			.reg		= _reg,					\
+			.hw.init	= CLK_HW_INIT_PARENTS(_name,		\
+							      _parents,		\
+							      &ccu_mux_ops,	\
+							      _flags),		\
+			.features	= _features,				\
+		}								\
+	}
+
+#define SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(_struct, _name, _parents,	\
+					      _table, _reg, _shift,	\
+					      _width, _gate, _flags)	\
+	SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,	\
+					   _table, _reg, _shift,	\
+					   _width, _gate, _flags,	\
+					   CCU_FEATURE_CLOSEST_RATE)
+
 #define SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, _table,	\
 				     _reg, _shift, _width, _gate,	\
 				     _flags)				\
-	struct ccu_mux _struct = {					\
-		.enable	= _gate,					\
-		.mux	= _SUNXI_CCU_MUX_TABLE(_shift, _width, _table),	\
-		.common	= {						\
-			.reg		= _reg,				\
-			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
-							      _parents, \
-							      &ccu_mux_ops, \
-							      _flags),	\
-		}							\
-	}
+	SUNXI_CCU_MUX_TABLE_WITH_GATE_FEAT(_struct, _name, _parents,	\
+					   _table, _reg, _shift,	\
+					   _width, _gate, _flags, 0)
 
 #define SUNXI_CCU_MUX_WITH_GATE(_struct, _name, _parents, _reg,		\
 				_shift, _width, _gate, _flags)		\

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 09/11] clk: sunxi-ng: div: Support finding closest rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (7 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 08/11] clk: sunxi-ng: mux: " Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 10/11] clk: sunxi-ng: a64: select closest rate for pll-video0 Frank Oltmanns
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

Add initalization macros for divisor clocks with mux
(SUNXI_CCU_M_WITH_MUX) to support finding the closest rate. This clock
type requires the appropriate flags to be set in the .common structure
(for the mux part of the clock) and the .div part.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_div.h | 30 ++++++++++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h
index 948e2b0c0c3b..90d49ee8e0cc 100644
--- a/drivers/clk/sunxi-ng/ccu_div.h
+++ b/drivers/clk/sunxi-ng/ccu_div.h
@@ -143,6 +143,26 @@ struct ccu_div {
 		},							\
 	}
 
+#define SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name,		\
+						_parents, _table,	\
+						_reg,			\
+						_mshift, _mwidth,	\
+						_muxshift, _muxwidth,	\
+						_gate, _flags)		\
+	struct ccu_div _struct = {					\
+		.enable	= _gate,					\
+		.div	= _SUNXI_CCU_DIV_FLAGS(_mshift, _mwidth, CLK_DIVIDER_ROUND_CLOSEST), \
+		.mux	= _SUNXI_CCU_MUX_TABLE(_muxshift, _muxwidth, _table), \
+		.common	= {						\
+			.reg		= _reg,				\
+			.hw.init	= CLK_HW_INIT_PARENTS(_name,	\
+							      _parents, \
+							      &ccu_div_ops, \
+							      _flags),	\
+			.features	= CCU_FEATURE_CLOSEST_RATE,	\
+		},							\
+	}
+
 #define SUNXI_CCU_M_WITH_MUX_GATE(_struct, _name, _parents, _reg,	\
 				  _mshift, _mwidth, _muxshift, _muxwidth, \
 				  _gate, _flags)			\
@@ -152,6 +172,16 @@ struct ccu_div {
 					_muxshift, _muxwidth,		\
 					_gate, _flags)
 
+#define SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(_struct, _name, _parents,	\
+					  _reg, _mshift, _mwidth,	\
+					  _muxshift, _muxwidth,		\
+					  _gate, _flags)		\
+	SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(_struct, _name,		\
+						_parents, NULL,		\
+						_reg, _mshift, _mwidth,	\
+						_muxshift, _muxwidth,	\
+						_gate, _flags)
+
 #define SUNXI_CCU_M_WITH_MUX(_struct, _name, _parents, _reg,		\
 			     _mshift, _mwidth, _muxshift, _muxwidth,	\
 			     _flags)					\

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 10/11] clk: sunxi-ng: a64: select closest rate for pll-video0
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (8 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 09/11] clk: sunxi-ng: div: " Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-07 12:43 ` [PATCH v6 11/11] clk: sunxi-ng: nkm: Prefer current parent rate Frank Oltmanns
  2023-08-09 16:44 ` [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Chen-Yu Tsai
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

Selecting the closest rate for pll-video0 instead of the closest rate
that is less than the requested rate has no downside for this clock,
while allowing for selecting a more suitable rate, e.g. for the
connected panels.

Furthermore, the algorithm that sets an NKM clock's parent benefits from
the closest rate. Without it, the NKM clock's rate might drift away from
the requested rate in the multiple successive calls to
ccu_nkm_determine_rate that the clk framework performs when setting a
clock rate.

Therefore, configure pll-video0 and, in consequence, all of its
descendents to select the closest rate.

Acked-by: Maxime Ripard <mripard@kernel.org>
Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 33 ++++++++++++++-------------------
 1 file changed, 14 insertions(+), 19 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index a139a5c438d4..73c84d20f3ee 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -68,7 +68,7 @@ static SUNXI_CCU_NM_WITH_SDM_GATE_LOCK(pll_audio_base_clk, "pll-audio-base",
 				       BIT(28),	/* lock */
 				       CLK_SET_RATE_UNGATE);
 
-static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX(pll_video0_clk, "pll-video0",
+static SUNXI_CCU_NM_WITH_FRAC_GATE_LOCK_MIN_MAX_CLOSEST(pll_video0_clk, "pll-video0",
 						"osc24M", 0x010,
 						192000000,	/* Minimum rate */
 						1008000000,	/* Maximum rate */
@@ -181,6 +181,7 @@ static struct ccu_nkm pll_mipi_clk = {
 		.hw.init	= CLK_HW_INIT("pll-mipi", "pll-video0",
 					      &ccu_nkm_ops,
 					      CLK_SET_RATE_UNGATE | CLK_SET_RATE_PARENT),
+		.features	= CCU_FEATURE_CLOSEST_RATE,
 	},
 };
 
@@ -531,24 +532,18 @@ static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_parents,
 
 static const char * const tcon0_parents[] = { "pll-mipi", "pll-video0-2x" };
 static const u8 tcon0_table[] = { 0, 2, };
-static SUNXI_CCU_MUX_TABLE_WITH_GATE(tcon0_clk, "tcon0", tcon0_parents,
+static SUNXI_CCU_MUX_TABLE_WITH_GATE_CLOSEST(tcon0_clk, "tcon0", tcon0_parents,
 				     tcon0_table, 0x118, 24, 3, BIT(31),
 				     CLK_SET_RATE_PARENT);
 
 static const char * const tcon1_parents[] = { "pll-video0", "pll-video1" };
 static const u8 tcon1_table[] = { 0, 2, };
-static struct ccu_div tcon1_clk = {
-	.enable		= BIT(31),
-	.div		= _SUNXI_CCU_DIV(0, 4),
-	.mux		= _SUNXI_CCU_MUX_TABLE(24, 2, tcon1_table),
-	.common		= {
-		.reg		= 0x11c,
-		.hw.init	= CLK_HW_INIT_PARENTS("tcon1",
-						      tcon1_parents,
-						      &ccu_div_ops,
-						      CLK_SET_RATE_PARENT),
-	},
-};
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(tcon1_clk, "tcon1", tcon1_parents,
+					       tcon1_table, 0x11c,
+					       0, 4,	/* M */
+					       24, 2,	/* mux */
+					       BIT(31),	/* gate */
+					       CLK_SET_RATE_PARENT);
 
 static const char * const deinterlace_parents[] = { "pll-periph0", "pll-periph1" };
 static SUNXI_CCU_M_WITH_MUX_GATE(deinterlace_clk, "deinterlace", deinterlace_parents,
@@ -578,8 +573,8 @@ static SUNXI_CCU_GATE(avs_clk,		"avs",		"osc24M",
 		      0x144, BIT(31), 0);
 
 static const char * const hdmi_parents[] = { "pll-video0", "pll-video1" };
-static SUNXI_CCU_M_WITH_MUX_GATE(hdmi_clk, "hdmi", hdmi_parents,
-				 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_MUX_GATE_CLOSEST(hdmi_clk, "hdmi", hdmi_parents,
+					 0x150, 0, 4, 24, 2, BIT(31), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_GATE(hdmi_ddc_clk,	"hdmi-ddc",	"osc24M",
 		      0x154, BIT(31), 0);
@@ -591,9 +586,9 @@ static SUNXI_CCU_M_WITH_MUX_GATE(mbus_clk, "mbus", mbus_parents,
 
 static const char * const dsi_dphy_parents[] = { "pll-video0", "pll-periph0" };
 static const u8 dsi_dphy_table[] = { 0, 2, };
-static SUNXI_CCU_M_WITH_MUX_TABLE_GATE(dsi_dphy_clk, "dsi-dphy",
-				       dsi_dphy_parents, dsi_dphy_table,
-				       0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
+static SUNXI_CCU_M_WITH_MUX_TABLE_GATE_CLOSEST(dsi_dphy_clk, "dsi-dphy",
+					       dsi_dphy_parents, dsi_dphy_table,
+					       0x168, 0, 4, 8, 2, BIT(15), CLK_SET_RATE_PARENT);
 
 static SUNXI_CCU_M_WITH_GATE(gpu_clk, "gpu", "pll-gpu",
 			     0x1a0, 0, 3, BIT(31), CLK_SET_RATE_PARENT);

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [PATCH v6 11/11] clk: sunxi-ng: nkm: Prefer current parent rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (9 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 10/11] clk: sunxi-ng: a64: select closest rate for pll-video0 Frank Oltmanns
@ 2023-08-07 12:43 ` Frank Oltmanns
  2023-08-09 16:44 ` [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Chen-Yu Tsai
  11 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-07 12:43 UTC (permalink / raw)
  To: Maxime Ripard, Michael Turquette, Stephen Boyd, Chen-Yu Tsai,
	Jernej Skrabec, Samuel Holland, Andre Przywara, Roman Beranek
  Cc: linux-clk, linux-arm-kernel, linux-sunxi, linux-kernel,
	Frank Oltmanns

Similar to ccu_mp, if the current parent rate allows getting the ideal
rate, prefer to not change the parent clock's rate.

Reviewed-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>
---
 drivers/clk/sunxi-ng/ccu_nkm.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index a714dcf0dfc1..eed64547ad42 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -34,7 +34,8 @@ static unsigned long ccu_nkm_find_best_with_parent_adj(struct ccu_common *common
 
 				tmp_rate = tmp_parent * _n * _k / _m;
 
-				if (ccu_is_better_rate(common, rate, tmp_rate, best_rate)) {
+				if (ccu_is_better_rate(common, rate, tmp_rate, best_rate) ||
+				    (tmp_parent == *parent && tmp_rate == best_rate)) {
 					best_rate = tmp_rate;
 					best_parent_rate = tmp_parent;
 					best_n = _n;

-- 
2.41.0


^ permalink raw reply related	[flat|nested] 15+ messages in thread

* Re: [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
  2023-08-07 12:43 ` [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate Frank Oltmanns
@ 2023-08-07 14:28   ` Chen-Yu Tsai
  0 siblings, 0 replies; 15+ messages in thread
From: Chen-Yu Tsai @ 2023-08-07 14:28 UTC (permalink / raw)
  To: Frank Oltmanns
  Cc: Maxime Ripard, Michael Turquette, Stephen Boyd, Jernej Skrabec,
	Samuel Holland, Andre Przywara, Roman Beranek, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 7, 2023 at 8:44 PM Frank Oltmanns <frank@oltmanns.dev> wrote:
>
> In case the CLK_SET_RATE_PARENT flag is set, consider using a different
> parent rate when determining a new rate.
>
> To find the best match for the requested rate, perform the following
> steps for each NKM combination:
>  - calculate the optimal parent rate,
>  - find the best parent rate that the parent clock actually supports
>  - use that parent rate to calculate the effective rate.
>
> In case the clk does not support setting the parent rate, use the same
> algorithm as before.
>
> Acked-by: Maxime Ripard <mripard@kernel.org>
> Signed-off-by: Frank Oltmanns <frank@oltmanns.dev>

Reviewed-by: Chen-Yu Tsai <wens@csie.org>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate
  2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
                   ` (10 preceding siblings ...)
  2023-08-07 12:43 ` [PATCH v6 11/11] clk: sunxi-ng: nkm: Prefer current parent rate Frank Oltmanns
@ 2023-08-09 16:44 ` Chen-Yu Tsai
  2023-08-09 18:58   ` Frank Oltmanns
  11 siblings, 1 reply; 15+ messages in thread
From: Chen-Yu Tsai @ 2023-08-09 16:44 UTC (permalink / raw)
  To: Frank Oltmanns
  Cc: Maxime Ripard, Michael Turquette, Stephen Boyd, Jernej Skrabec,
	Samuel Holland, Andre Przywara, Roman Beranek, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel

On Mon, Aug 7, 2023 at 8:44 PM Frank Oltmanns <frank@oltmanns.dev> wrote:
>
> This patchset enables NKM clocks to consider alternative parent rates
> and utilize this new feature to adjust the pll-video0 clock on Allwinner
> A64.
>
> Furthermore, with this patchset pll-video0 considers rates that are
> higher than the requested rate when finding the closest rate. In
> consequence, higher rates are also considered by pll-video0's
> descandents. In total, after applying this patchset, finding the closest
> rate is supported by:
>   - ccu_nm
>   - ccu_nkm
>   - ccu_mux
>   - ccu_div
>
> This allows us to achieve an optimal rate for driving the board's panel.
>
> To provide some context, the clock structure involved in this process is
> as follows:
>     clock                       clock type
>     --------------------------------------
>     pll-video0                  ccu_nm
>        pll-mipi                 ccu_nkm
>           tcon0                 ccu_mux
>              tcon-data-clock    sun4i_dclk
>
> The divider between tcon0 and tcon-data-clock is fixed at 4. Therefore,
> in order to achieve a rate that closely matches the desired rate of the
> panel, pll-mipi needs to operate at a specific rate.
>
> Tests
> =====
> So far, this has been successfully tested on the A64-based Pinephone
> using three different panel rates:
>
>  1. A panel rate that can be matched exactly by pll-video0.
>  2. A panel rate that requires pll-video0 to undershoot to get the
>     closest rate.
>  3. A panel rate that requires pll-video0 to overshoot to get the
>     closest rate.
>
> Test records:
>
> Re 1:
> -----
> Panel requests tcon-data-clock of 103500000 Hz, i.e., pll-mipi needs to
> run at 414000000 Hz. This results in the following clock rates:
>    clock                            rate
>    -------------------------------------
>     pll-video0                 207000000
>        hdmi-phy-clk             51750000
>        hdmi                    207000000
>        tcon1                   207000000
>        pll-mipi                414000000
>           tcon0                414000000
>              tcon-data-clock   103500000
>
> The results of the find_best calls:
> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
> ccu_nkm_find_best: rate=414000000, best_rate=414000000, parent_rate=207000000, n=1, k=2, m=1
>
> Re 2:
> -----
> Panel requests tcon-data-clock of 103650000 Hz, i.e., pll-mipi needs to
> run at 414600000 Hz. This results in the following clock rates:
>    clock                            rate
>    -------------------------------------
>     pll-video0                 282666666
>        hdmi-phy-clk             70666666
>        hdmi                    282666666
>        tcon1                   282666666
>        pll-mipi                414577776
>           tcon0                414577776
>              tcon-data-clock   103644444
>
> The results of the find_best calls:
> ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
> ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
> ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
> ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
> ccu_nkm_find_best: rate=414577776, best_rate=414577776, parent_rate=282666666, n=11, k=2, m=15
>
> Re 3:
> -----
> Panel requests tcon-data-clock of 112266000 Hz, i.e., pll-mipi needs to
> run at 449064000 Hz. This results in the following clock rates:
>    clock                            rate
>    -------------------------------------
>     pll-video0                 207272727
>        hdmi-phy-clk             51818181
>        hdmi                    207272727
>        tcon1                   207272727
>        pll-mipi                449090908
>           tcon0                449090908
>              tcon-data-clock   112272727
>
> The results of the find_best calls:
> ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
> ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
> ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
> ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
> ccu_nkm_find_best: rate=449090908, best_rate=449090908, parent_rate=207272727, n=13, k=2, m=12
>
> Changelog:
> ----------
> Changes in v6:
>  - Removed unnecessary #include from ccu_nkm.c
>  - Link to v5: https://lore.kernel.org/r/20230806-pll-mipi_set_rate_parent-v5-0-db4f5ca33fc3@oltmanns.dev
>
> Changes in v5:
>  - Remove the dedicated function for calculating the optimal parent rate
>    for nkm clocks that was introduced in v2 and again in v4. Instead use
>    a simple calculation and require the parent clock to select the
>    closest rate to achieve optimal results.
>  - Change the order of parameters of nkm_best_rate and
>    nkm_best_rate_with_parent_adj as requested my Maxime Ripard.
>  - Prefer to not reset the rate of the nkm clock's parent if the ideal
>    rate can be reached using the parent's current rate, copying the
>    behavior of ccu_mp.
>  - Link to v4: https://lore.kernel.org/r/20230717-pll-mipi_set_rate_parent-v4-0-04acf1d39765@oltmanns.dev
>
> Changes in v4:
>  - Re-introduce a dedicated function for calculating the optimal parent
>    rate for nkm clocks that was introduced in v2 and removed in v3. It
>    turned out that not having this functionality introduces a bug when
>    the parent does not support finding the closest rate:
>    https://lore.kernel.org/all/87pm4xg2ub.fsf@oltmanns.dev/
>  - Incorporate review remarks:
>     - Correcting the parameter name for ccu_nkm_round_rate()'s parent HW
>       is now in a separate patch.
>     - Use correct parameter order in ccu_nkm_find_best_with_parent_adj.
>     - Add ccu_is_better_rate() and use it for determining the best rate
>       for nm and nkm, as well as ccu_mux_helper_determine_rate.
>     - Consistently introduce new macros for clock variants that support
>       finding the closest rate instead of updating existing macros.
>     - Use wrapper function for determining a ccu_mux's rate in order to
>       support finding the closest rate.
>  - Link to v3: https://lore.kernel.org/r/20230702-pll-mipi_set_rate_parent-v3-0-46dcb8aa9cbc@oltmanns.dev
>
> Changes in v3:
>  - Use dedicated function for finding the best rate in cases where an
>    nkm clock supports setting its parent's rate, streamlining it with
>    the structure that is used in other sunxi-ng ccus such as ccu_mp
>    (PATCH 1).
>  - Therefore, remove the now obsolete comments that were introduced in
>    v2 (PATCH 1).
>  - Remove the dedicated function for calculating the optimal parent rate
>    for nkm clocks that was introduced in v2. Instead use a simple
>    calculation and require the parent clock to select the closest rate to
>    achieve optimal results (PATCH 1).
>  - Therefore, add support to set the closest rate for nm clocks (because
>    pll-mipi's parent pll-video0 is an nm clock) and all clock types that
>    are descendants of a64's pll-video0, i.e., nkm, mux, and div (PATCH 3
>    et. seq.).
>  - Link to v2: https://lore.kernel.org/all/20230611090143.132257-1-frank@oltmanns.dev/
>
> Changes in V2:
>  - Move optimal parent rate calculation to dedicated function
>  - Choose a parent rate that does not to overshoot requested rate
>  - Add comments to ccu_nkm_find_best
>  - Make sure that best_parent_rate stays at original parent rate in the unlikely
>    case that all combinations overshoot.
>
> Link to V1:
> https://lore.kernel.org/lkml/20230605190745.366882-1-frank@oltmanns.dev/
>
> ---
> Frank Oltmanns (11):
>       clk: sunxi-ng: nkm: Use correct parameter name for parent HW
>       clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
>       clk: sunxi-ng: a64: allow pll-mipi to set parent's rate
>       clk: sunxi-ng: Add feature to find closest rate
>       clk: sunxi-ng: Add helper function to find closest rate
>       clk: sunxi-ng: nm: Support finding closest rate
>       clk: sunxi-ng: nkm: Support finding closest rate
>       clk: sunxi-ng: mux: Support finding closest rate
>       clk: sunxi-ng: div: Support finding closest rate
>       clk: sunxi-ng: a64: select closest rate for pll-video0
>       clk: sunxi-ng: nkm: Prefer current parent rate

Whole series applied. There were some conflicts on patch 10 I had to
fix up. I also took the liberty of realigning some of the lines.
Please check if things are correct:

https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git/commit/?h=sunxi/clk-for-6.6&id=bf8eb12f52c49e10ca1d86564bfa096e09c51c38

ChenYu

>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 36 ++++++++++-------------
>  drivers/clk/sunxi-ng/ccu_common.c     | 12 ++++++++
>  drivers/clk/sunxi-ng/ccu_common.h     |  6 ++++
>  drivers/clk/sunxi-ng/ccu_div.h        | 30 +++++++++++++++++++
>  drivers/clk/sunxi-ng/ccu_mux.c        | 15 ++++++++--
>  drivers/clk/sunxi-ng/ccu_mux.h        | 38 +++++++++++++++++-------
>  drivers/clk/sunxi-ng/ccu_nkm.c        | 55 ++++++++++++++++++++++++++++++-----
>  drivers/clk/sunxi-ng/ccu_nm.c         | 13 ++++-----
>  drivers/clk/sunxi-ng/ccu_nm.h         | 48 ++++++++++++++++++++++++++++--
>  9 files changed, 202 insertions(+), 51 deletions(-)
> ---
> base-commit: 6995e2de6891c724bfeb2db33d7b87775f913ad1
> change-id: 20230626-pll-mipi_set_rate_parent-3363fc0d6e6f
>
> Best regards,
> --
> Frank Oltmanns <frank@oltmanns.dev>
>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate
  2023-08-09 16:44 ` [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Chen-Yu Tsai
@ 2023-08-09 18:58   ` Frank Oltmanns
  0 siblings, 0 replies; 15+ messages in thread
From: Frank Oltmanns @ 2023-08-09 18:58 UTC (permalink / raw)
  To: wens
  Cc: Maxime Ripard, Michael Turquette, Stephen Boyd, Jernej Skrabec,
	Samuel Holland, Andre Przywara, Roman Beranek, linux-clk,
	linux-arm-kernel, linux-sunxi, linux-kernel


On 2023-08-10 at 00:44:53 +0800, Chen-Yu Tsai <wens@csie.org> wrote:
> On Mon, Aug 7, 2023 at 8:44 PM Frank Oltmanns <frank@oltmanns.dev> wrote:
>>
>> This patchset enables NKM clocks to consider alternative parent rates
>> and utilize this new feature to adjust the pll-video0 clock on Allwinner
>> A64.
>>
>> Furthermore, with this patchset pll-video0 considers rates that are
>> higher than the requested rate when finding the closest rate. In
>> consequence, higher rates are also considered by pll-video0's
>> descandents. In total, after applying this patchset, finding the closest
>> rate is supported by:
>>   - ccu_nm
>>   - ccu_nkm
>>   - ccu_mux
>>   - ccu_div
>>
>> This allows us to achieve an optimal rate for driving the board's panel.
>>
>> To provide some context, the clock structure involved in this process is
>> as follows:
>>     clock                       clock type
>>     --------------------------------------
>>     pll-video0                  ccu_nm
>>        pll-mipi                 ccu_nkm
>>           tcon0                 ccu_mux
>>              tcon-data-clock    sun4i_dclk
>>
>> The divider between tcon0 and tcon-data-clock is fixed at 4. Therefore,
>> in order to achieve a rate that closely matches the desired rate of the
>> panel, pll-mipi needs to operate at a specific rate.
>>
>> Tests
>> =====
>> So far, this has been successfully tested on the A64-based Pinephone
>> using three different panel rates:
>>
>>  1. A panel rate that can be matched exactly by pll-video0.
>>  2. A panel rate that requires pll-video0 to undershoot to get the
>>     closest rate.
>>  3. A panel rate that requires pll-video0 to overshoot to get the
>>     closest rate.
>>
>> Test records:
>>
>> Re 1:
>> -----
>> Panel requests tcon-data-clock of 103500000 Hz, i.e., pll-mipi needs to
>> run at 414000000 Hz. This results in the following clock rates:
>>    clock                            rate
>>    -------------------------------------
>>     pll-video0                 207000000
>>        hdmi-phy-clk             51750000
>>        hdmi                    207000000
>>        tcon1                   207000000
>>        pll-mipi                414000000
>>           tcon0                414000000
>>              tcon-data-clock   103500000
>>
>> The results of the find_best calls:
>> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
>> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
>> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
>> ccu_nkm_find_best_with_parent_adj: rate=414000000, best_rate=414000000, best_parent_rate=207000000, n=1, k=2, m=1
>> ccu_nkm_find_best: rate=414000000, best_rate=414000000, parent_rate=207000000, n=1, k=2, m=1
>>
>> Re 2:
>> -----
>> Panel requests tcon-data-clock of 103650000 Hz, i.e., pll-mipi needs to
>> run at 414600000 Hz. This results in the following clock rates:
>>    clock                            rate
>>    -------------------------------------
>>     pll-video0                 282666666
>>        hdmi-phy-clk             70666666
>>        hdmi                    282666666
>>        tcon1                   282666666
>>        pll-mipi                414577776
>>           tcon0                414577776
>>              tcon-data-clock   103644444
>>
>> The results of the find_best calls:
>> ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
>> ccu_nkm_find_best_with_parent_adj: rate=414600000, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
>> ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
>> ccu_nkm_find_best_with_parent_adj: rate=414577776, best_rate=414577776, best_parent_rate=282666666, n=11, k=2, m=15
>> ccu_nkm_find_best: rate=414577776, best_rate=414577776, parent_rate=282666666, n=11, k=2, m=15
>>
>> Re 3:
>> -----
>> Panel requests tcon-data-clock of 112266000 Hz, i.e., pll-mipi needs to
>> run at 449064000 Hz. This results in the following clock rates:
>>    clock                            rate
>>    -------------------------------------
>>     pll-video0                 207272727
>>        hdmi-phy-clk             51818181
>>        hdmi                    207272727
>>        tcon1                   207272727
>>        pll-mipi                449090908
>>           tcon0                449090908
>>              tcon-data-clock   112272727
>>
>> The results of the find_best calls:
>> ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
>> ccu_nkm_find_best_with_parent_adj: rate=449064000, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
>> ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
>> ccu_nkm_find_best_with_parent_adj: rate=449090908, best_rate=449090908, best_parent_rate=207272727, n=13, k=2, m=12
>> ccu_nkm_find_best: rate=449090908, best_rate=449090908, parent_rate=207272727, n=13, k=2, m=12
>>
>> Changelog:
>> ----------
>> Changes in v6:
>>  - Removed unnecessary #include from ccu_nkm.c
>>  - Link to v5: https://lore.kernel.org/r/20230806-pll-mipi_set_rate_parent-v5-0-db4f5ca33fc3@oltmanns.dev
>>
>> Changes in v5:
>>  - Remove the dedicated function for calculating the optimal parent rate
>>    for nkm clocks that was introduced in v2 and again in v4. Instead use
>>    a simple calculation and require the parent clock to select the
>>    closest rate to achieve optimal results.
>>  - Change the order of parameters of nkm_best_rate and
>>    nkm_best_rate_with_parent_adj as requested my Maxime Ripard.
>>  - Prefer to not reset the rate of the nkm clock's parent if the ideal
>>    rate can be reached using the parent's current rate, copying the
>>    behavior of ccu_mp.
>>  - Link to v4: https://lore.kernel.org/r/20230717-pll-mipi_set_rate_parent-v4-0-04acf1d39765@oltmanns.dev
>>
>> Changes in v4:
>>  - Re-introduce a dedicated function for calculating the optimal parent
>>    rate for nkm clocks that was introduced in v2 and removed in v3. It
>>    turned out that not having this functionality introduces a bug when
>>    the parent does not support finding the closest rate:
>>    https://lore.kernel.org/all/87pm4xg2ub.fsf@oltmanns.dev/
>>  - Incorporate review remarks:
>>     - Correcting the parameter name for ccu_nkm_round_rate()'s parent HW
>>       is now in a separate patch.
>>     - Use correct parameter order in ccu_nkm_find_best_with_parent_adj.
>>     - Add ccu_is_better_rate() and use it for determining the best rate
>>       for nm and nkm, as well as ccu_mux_helper_determine_rate.
>>     - Consistently introduce new macros for clock variants that support
>>       finding the closest rate instead of updating existing macros.
>>     - Use wrapper function for determining a ccu_mux's rate in order to
>>       support finding the closest rate.
>>  - Link to v3: https://lore.kernel.org/r/20230702-pll-mipi_set_rate_parent-v3-0-46dcb8aa9cbc@oltmanns.dev
>>
>> Changes in v3:
>>  - Use dedicated function for finding the best rate in cases where an
>>    nkm clock supports setting its parent's rate, streamlining it with
>>    the structure that is used in other sunxi-ng ccus such as ccu_mp
>>    (PATCH 1).
>>  - Therefore, remove the now obsolete comments that were introduced in
>>    v2 (PATCH 1).
>>  - Remove the dedicated function for calculating the optimal parent rate
>>    for nkm clocks that was introduced in v2. Instead use a simple
>>    calculation and require the parent clock to select the closest rate to
>>    achieve optimal results (PATCH 1).
>>  - Therefore, add support to set the closest rate for nm clocks (because
>>    pll-mipi's parent pll-video0 is an nm clock) and all clock types that
>>    are descendants of a64's pll-video0, i.e., nkm, mux, and div (PATCH 3
>>    et. seq.).
>>  - Link to v2: https://lore.kernel.org/all/20230611090143.132257-1-frank@oltmanns.dev/
>>
>> Changes in V2:
>>  - Move optimal parent rate calculation to dedicated function
>>  - Choose a parent rate that does not to overshoot requested rate
>>  - Add comments to ccu_nkm_find_best
>>  - Make sure that best_parent_rate stays at original parent rate in the unlikely
>>    case that all combinations overshoot.
>>
>> Link to V1:
>> https://lore.kernel.org/lkml/20230605190745.366882-1-frank@oltmanns.dev/
>>
>> ---
>> Frank Oltmanns (11):
>>       clk: sunxi-ng: nkm: Use correct parameter name for parent HW
>>       clk: sunxi-ng: nkm: consider alternative parent rates when determining rate
>>       clk: sunxi-ng: a64: allow pll-mipi to set parent's rate
>>       clk: sunxi-ng: Add feature to find closest rate
>>       clk: sunxi-ng: Add helper function to find closest rate
>>       clk: sunxi-ng: nm: Support finding closest rate
>>       clk: sunxi-ng: nkm: Support finding closest rate
>>       clk: sunxi-ng: mux: Support finding closest rate
>>       clk: sunxi-ng: div: Support finding closest rate
>>       clk: sunxi-ng: a64: select closest rate for pll-video0
>>       clk: sunxi-ng: nkm: Prefer current parent rate
>
> Whole series applied. There were some conflicts on patch 10 I had to
> fix up. I also took the liberty of realigning some of the lines.
> Please check if things are correct:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git/commit/?h=sunxi/clk-for-6.6&id=bf8eb12f52c49e10ca1d86564bfa096e09c51c38
>

Thank you. I'm sorry, I used the wrong base-commit. Yours looks perfect!

Also thank you for re-indenting. Looks cleaner.

Best regards,
  Frank

>
> ChenYu
>
>>  drivers/clk/sunxi-ng/ccu-sun50i-a64.c | 36 ++++++++++-------------
>>  drivers/clk/sunxi-ng/ccu_common.c     | 12 ++++++++
>>  drivers/clk/sunxi-ng/ccu_common.h     |  6 ++++
>>  drivers/clk/sunxi-ng/ccu_div.h        | 30 +++++++++++++++++++
>>  drivers/clk/sunxi-ng/ccu_mux.c        | 15 ++++++++--
>>  drivers/clk/sunxi-ng/ccu_mux.h        | 38 +++++++++++++++++-------
>>  drivers/clk/sunxi-ng/ccu_nkm.c        | 55 ++++++++++++++++++++++++++++++-----
>>  drivers/clk/sunxi-ng/ccu_nm.c         | 13 ++++-----
>>  drivers/clk/sunxi-ng/ccu_nm.h         | 48 ++++++++++++++++++++++++++++--
>>  9 files changed, 202 insertions(+), 51 deletions(-)
>> ---
>> base-commit: 6995e2de6891c724bfeb2db33d7b87775f913ad1
>> change-id: 20230626-pll-mipi_set_rate_parent-3363fc0d6e6f
>>
>> Best regards,
>> --
>> Frank Oltmanns <frank@oltmanns.dev>
>>

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2023-08-09 18:58 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-08-07 12:43 [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 01/11] clk: sunxi-ng: nkm: Use correct parameter name for parent HW Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 02/11] clk: sunxi-ng: nkm: consider alternative parent rates when determining rate Frank Oltmanns
2023-08-07 14:28   ` Chen-Yu Tsai
2023-08-07 12:43 ` [PATCH v6 03/11] clk: sunxi-ng: a64: allow pll-mipi to set parent's rate Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 04/11] clk: sunxi-ng: Add feature to find closest rate Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 05/11] clk: sunxi-ng: Add helper function " Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 06/11] clk: sunxi-ng: nm: Support finding " Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 07/11] clk: sunxi-ng: nkm: " Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 08/11] clk: sunxi-ng: mux: " Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 09/11] clk: sunxi-ng: div: " Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 10/11] clk: sunxi-ng: a64: select closest rate for pll-video0 Frank Oltmanns
2023-08-07 12:43 ` [PATCH v6 11/11] clk: sunxi-ng: nkm: Prefer current parent rate Frank Oltmanns
2023-08-09 16:44 ` [PATCH v6 00/11] clk: sunxi-ng: Consider alternative parent rates when determining NKM clock rate Chen-Yu Tsai
2023-08-09 18:58   ` Frank Oltmanns

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).