All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ziyang Huang <hzyitc@outlook.com>
To: mcoquelin.stm32@gmail.com
Cc: alexandre.torgue@foss.st.com, richardcochran@gmail.com,
	p.zabel@pengutronix.de, matthias.bgg@gmail.com,
	angelogioacchino.delregno@collabora.com,
	linux-kernel@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org,
	linux-mediatek@lists.infradead.org,
	Praveenkumar I <ipkumar@codeaurora.org>,
	Abhishek Sahu <absahu@codeaurora.org>,
	Ziyang Huang <hzyitc@outlook.com>
Subject: [PATCH 5/8] clk: qcom: support for duplicate freq in RCG2 freq table
Date: Sun, 21 Jan 2024 20:42:34 +0800	[thread overview]
Message-ID: <TYZPR01MB5556DEA3D4740441EC561414C9762@TYZPR01MB5556.apcprd01.prod.exchangelabs.com> (raw)
In-Reply-To: <TYZPR01MB55563BD6A2B78402E4BB44D4C9762@TYZPR01MB5556.apcprd01.prod.exchangelabs.com>

From: Praveenkumar I <ipkumar@codeaurora.org>

Currently RCG code looks up the frequency table during set
rate and return the first available frequency greater than
requested rate. If CLK_SET_RATE_PARENT flag is set then the
set_rate request will go to its parent otherwise the clock
framework will configure pre-div, m and n according to the
returned frequency table entry. In this case, it is assuming
that parent clock will run in the same frequency with which
pre-div, m and n has been derived. But it may be possible
that the parent clock supports multiple frequency and the
same frequency can be derived with different pre-div, m and
n values depending upon current frequency.  Also, the same
frequency can be derived from different parent sources and
currently there is no option for having duplicate
frequencies in frequency table and choosing the best one
according to current rate.

Now this patch adds the support for having duplicate
frequencies in frequency table. During set rate, it will
compare the actual rate for each entry with requested rate
and will select the best entry in which the difference will
be less.

The existing functionality won’t be affected with this code
change since this code change will hit only if frequency
table has duplicate values.

Change-Id: I97d9e1b55d8f3ee095f6f01729af527ba90e50e5
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
(cherry picked from commit 775e7d3b69ffc97afb5bd5a6c9c423f2f4d8a0b2)
Signed-off-by: Praveenkumar I <ipkumar@codeaurora.org>

Change-Id: If10193fc79a3c1375ab73597813745ff1f4df0ad

Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/6dfb368bae130bee58e00ddf8330b55066e1c8c5

Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
 drivers/clk/qcom/clk-rcg2.c | 86 ++++++++++++++++++++++++++++---------
 1 file changed, 66 insertions(+), 20 deletions(-)

diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index e22baf3a7112..6141e4991fbc 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -209,26 +209,82 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 	return __clk_rcg2_recalc_rate(hw, parent_rate, cfg);
 }
 
-static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
-				    struct clk_rate_request *req,
-				    enum freq_policy policy)
+static const struct freq_tbl *
+clk_rcg2_find_best_freq(struct clk_hw *hw, const struct freq_tbl *f,
+			unsigned long rate, enum freq_policy policy)
 {
-	unsigned long clk_flags, rate = req->rate;
-	struct clk_hw *p;
+	unsigned long req_rate = rate, best = 0, freq;
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	int index;
+	u64 tmp;
+	const struct freq_tbl *best_ftable = NULL;
 
 	switch (policy) {
 	case FLOOR:
-		f = qcom_find_freq_floor(f, rate);
+		f = qcom_find_freq_floor(rcg->freq_tbl, rate);
 		break;
 	case CEIL:
-		f = qcom_find_freq(f, rate);
+		f = qcom_find_freq(rcg->freq_tbl, rate);
 		break;
 	default:
-		return -EINVAL;
+		return best_ftable;
 	}
 
+	/*
+	 * Check for duplicate frequencies in frequency table if
+	 * CLK_SET_RATE_PARENT flag is not set
+	 */
+	if (!f || (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) ||
+	    ((f->freq && (f + 1)->freq != f->freq)))
+		return f;
+
+	/*
+	 * Check for all the duplicate entries in frequency table and
+	 * calculate the actual rate from current parent rate with each
+	 * entries pre_div, m and n values. The entry, which gives the
+	 * minimum difference in requested rate and actual rate, will be
+	 * selected as the best one.
+	 */
+	for (freq = f->freq; freq == f->freq; f++) {
+		index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+		if (index < 0)
+			continue;
+
+		rate =  clk_hw_get_rate(clk_hw_get_parent_by_index(hw, index));
+		if (rcg->hid_width && f->pre_div) {
+			rate *= 2;
+			rate /= f->pre_div + 1;
+		}
+
+		if (rcg->mnd_width && f->n) {
+			tmp = rate;
+			tmp = tmp * f->n;
+			do_div(tmp, f->m);
+			rate = tmp;
+		}
+
+		if (abs(req_rate - rate) < abs(best - rate)) {
+			best_ftable = f;
+			best = rate;
+
+			if (req_rate == rate)
+				break;
+		}
+	}
+
+	return best_ftable;
+}
+
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+				    struct clk_rate_request *req,
+				    enum freq_policy policy)
+{
+	unsigned long clk_flags, rate = req->rate;
+	struct clk_hw *p;
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	int index;
+
+	f = clk_rcg2_find_best_freq(hw, f, rate, policy);
 	if (!f)
 		return -EINVAL;
 
@@ -360,17 +416,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
 
-	switch (policy) {
-	case FLOOR:
-		f = qcom_find_freq_floor(rcg->freq_tbl, rate);
-		break;
-	case CEIL:
-		f = qcom_find_freq(rcg->freq_tbl, rate);
-		break;
-	default:
-		return -EINVAL;
-	}
-
+	f = clk_rcg2_find_best_freq(hw, rcg->freq_tbl, rate, policy);
 	if (!f)
 		return -EINVAL;
 
@@ -1032,7 +1078,7 @@ static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
 
-	f = qcom_find_freq(rcg->freq_tbl, rate);
+	f = clk_rcg2_find_best_freq(hw, rcg->freq_tbl, rate, CEIL);
 	if (!f)
 		return -EINVAL;
 
-- 
2.40.1


WARNING: multiple messages have this Message-ID (diff)
From: Ziyang Huang <hzyitc@outlook.com>
To: mcoquelin.stm32@gmail.com
Cc: alexandre.torgue@foss.st.com, richardcochran@gmail.com,
	p.zabel@pengutronix.de, matthias.bgg@gmail.com,
	angelogioacchino.delregno@collabora.com,
	linux-kernel@vger.kernel.org,
	linux-stm32@st-md-mailman.stormreply.com,
	linux-arm-kernel@lists.infradead.org, netdev@vger.kernel.org,
	linux-mediatek@lists.infradead.org,
	Praveenkumar I <ipkumar@codeaurora.org>,
	Abhishek Sahu <absahu@codeaurora.org>,
	Ziyang Huang <hzyitc@outlook.com>
Subject: [PATCH 5/8] clk: qcom: support for duplicate freq in RCG2 freq table
Date: Sun, 21 Jan 2024 20:42:34 +0800	[thread overview]
Message-ID: <TYZPR01MB5556DEA3D4740441EC561414C9762@TYZPR01MB5556.apcprd01.prod.exchangelabs.com> (raw)
In-Reply-To: <TYZPR01MB55563BD6A2B78402E4BB44D4C9762@TYZPR01MB5556.apcprd01.prod.exchangelabs.com>

From: Praveenkumar I <ipkumar@codeaurora.org>

Currently RCG code looks up the frequency table during set
rate and return the first available frequency greater than
requested rate. If CLK_SET_RATE_PARENT flag is set then the
set_rate request will go to its parent otherwise the clock
framework will configure pre-div, m and n according to the
returned frequency table entry. In this case, it is assuming
that parent clock will run in the same frequency with which
pre-div, m and n has been derived. But it may be possible
that the parent clock supports multiple frequency and the
same frequency can be derived with different pre-div, m and
n values depending upon current frequency.  Also, the same
frequency can be derived from different parent sources and
currently there is no option for having duplicate
frequencies in frequency table and choosing the best one
according to current rate.

Now this patch adds the support for having duplicate
frequencies in frequency table. During set rate, it will
compare the actual rate for each entry with requested rate
and will select the best entry in which the difference will
be less.

The existing functionality won’t be affected with this code
change since this code change will hit only if frequency
table has duplicate values.

Change-Id: I97d9e1b55d8f3ee095f6f01729af527ba90e50e5
Signed-off-by: Abhishek Sahu <absahu@codeaurora.org>
(cherry picked from commit 775e7d3b69ffc97afb5bd5a6c9c423f2f4d8a0b2)
Signed-off-by: Praveenkumar I <ipkumar@codeaurora.org>

Change-Id: If10193fc79a3c1375ab73597813745ff1f4df0ad

Pick from https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/6dfb368bae130bee58e00ddf8330b55066e1c8c5

Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
 drivers/clk/qcom/clk-rcg2.c | 86 ++++++++++++++++++++++++++++---------
 1 file changed, 66 insertions(+), 20 deletions(-)

diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index e22baf3a7112..6141e4991fbc 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -209,26 +209,82 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
 	return __clk_rcg2_recalc_rate(hw, parent_rate, cfg);
 }
 
-static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
-				    struct clk_rate_request *req,
-				    enum freq_policy policy)
+static const struct freq_tbl *
+clk_rcg2_find_best_freq(struct clk_hw *hw, const struct freq_tbl *f,
+			unsigned long rate, enum freq_policy policy)
 {
-	unsigned long clk_flags, rate = req->rate;
-	struct clk_hw *p;
+	unsigned long req_rate = rate, best = 0, freq;
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	int index;
+	u64 tmp;
+	const struct freq_tbl *best_ftable = NULL;
 
 	switch (policy) {
 	case FLOOR:
-		f = qcom_find_freq_floor(f, rate);
+		f = qcom_find_freq_floor(rcg->freq_tbl, rate);
 		break;
 	case CEIL:
-		f = qcom_find_freq(f, rate);
+		f = qcom_find_freq(rcg->freq_tbl, rate);
 		break;
 	default:
-		return -EINVAL;
+		return best_ftable;
 	}
 
+	/*
+	 * Check for duplicate frequencies in frequency table if
+	 * CLK_SET_RATE_PARENT flag is not set
+	 */
+	if (!f || (clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT) ||
+	    ((f->freq && (f + 1)->freq != f->freq)))
+		return f;
+
+	/*
+	 * Check for all the duplicate entries in frequency table and
+	 * calculate the actual rate from current parent rate with each
+	 * entries pre_div, m and n values. The entry, which gives the
+	 * minimum difference in requested rate and actual rate, will be
+	 * selected as the best one.
+	 */
+	for (freq = f->freq; freq == f->freq; f++) {
+		index = qcom_find_src_index(hw, rcg->parent_map, f->src);
+		if (index < 0)
+			continue;
+
+		rate =  clk_hw_get_rate(clk_hw_get_parent_by_index(hw, index));
+		if (rcg->hid_width && f->pre_div) {
+			rate *= 2;
+			rate /= f->pre_div + 1;
+		}
+
+		if (rcg->mnd_width && f->n) {
+			tmp = rate;
+			tmp = tmp * f->n;
+			do_div(tmp, f->m);
+			rate = tmp;
+		}
+
+		if (abs(req_rate - rate) < abs(best - rate)) {
+			best_ftable = f;
+			best = rate;
+
+			if (req_rate == rate)
+				break;
+		}
+	}
+
+	return best_ftable;
+}
+
+static int _freq_tbl_determine_rate(struct clk_hw *hw, const struct freq_tbl *f,
+				    struct clk_rate_request *req,
+				    enum freq_policy policy)
+{
+	unsigned long clk_flags, rate = req->rate;
+	struct clk_hw *p;
+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+	int index;
+
+	f = clk_rcg2_find_best_freq(hw, f, rate, policy);
 	if (!f)
 		return -EINVAL;
 
@@ -360,17 +416,7 @@ static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
 
-	switch (policy) {
-	case FLOOR:
-		f = qcom_find_freq_floor(rcg->freq_tbl, rate);
-		break;
-	case CEIL:
-		f = qcom_find_freq(rcg->freq_tbl, rate);
-		break;
-	default:
-		return -EINVAL;
-	}
-
+	f = clk_rcg2_find_best_freq(hw, rcg->freq_tbl, rate, policy);
 	if (!f)
 		return -EINVAL;
 
@@ -1032,7 +1078,7 @@ static int clk_rcg2_shared_set_rate(struct clk_hw *hw, unsigned long rate,
 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
 	const struct freq_tbl *f;
 
-	f = qcom_find_freq(rcg->freq_tbl, rate);
+	f = clk_rcg2_find_best_freq(hw, rcg->freq_tbl, rate, CEIL);
 	if (!f)
 		return -EINVAL;
 
-- 
2.40.1


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

  parent reply	other threads:[~2024-01-21 12:43 UTC|newest]

Thread overview: 70+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-01-21 12:40 [PATCH 0/8] ipq5018: enable ethernet support Ziyang Huang
2024-01-21 12:40 ` Ziyang Huang
2024-01-21 12:42 ` [PATCH 1/8] net: phy: Introduce Qualcomm IPQ5018 internal PHY driver Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-21 16:19   ` Andrew Lunn
2024-01-21 16:19     ` Andrew Lunn
2024-01-22 15:37     ` Ziyang Huang
2024-01-22 15:37       ` Ziyang Huang
2024-01-22 17:18       ` Andrew Lunn
2024-01-22 17:18         ` Andrew Lunn
2024-01-23 15:38         ` Ziyang Huang
2024-01-23 15:38           ` Ziyang Huang
2024-01-23 23:15           ` Andrew Lunn
2024-01-23 23:15             ` Andrew Lunn
2024-01-21 12:42 ` [PATCH 2/8] phy: Introduce Qualcomm ethernet uniphy driver Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-23 15:58   ` Ziyang Huang
2024-01-23 15:58     ` Ziyang Huang
2024-01-23 23:25     ` Andrew Lunn
2024-01-23 23:25       ` Andrew Lunn
2024-01-21 12:42 ` [PATCH 3/8] net: stmmac: Introduce Qualcomm IPQ50xx DWMAC driver Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-24  5:54   ` kernel test robot
2024-01-24  5:54     ` kernel test robot
2024-01-24  9:40   ` kernel test robot
2024-01-24  9:40     ` kernel test robot
2024-01-21 12:42 ` [PATCH 4/8] clk: qcom: gcc-ipq5018: correct gcc_gmac0_sys_clk reg Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-21 16:28   ` Andrew Lunn
2024-01-21 16:28     ` Andrew Lunn
2024-01-22 15:39     ` Ziyang Huang
2024-01-22 15:39       ` Ziyang Huang
2024-01-21 12:42 ` Ziyang Huang [this message]
2024-01-21 12:42   ` [PATCH 5/8] clk: qcom: support for duplicate freq in RCG2 freq table Ziyang Huang
2024-01-21 16:57   ` Andrew Lunn
2024-01-21 16:57     ` Andrew Lunn
2024-01-22 16:35     ` Ziyang Huang
2024-01-22 16:35       ` Ziyang Huang
2024-01-22 17:34       ` Andrew Lunn
2024-01-22 17:34         ` Andrew Lunn
2024-01-23 15:43         ` Ziyang Huang
2024-01-23 15:43           ` Ziyang Huang
2024-01-22  7:55   ` Krzysztof Kozlowski
2024-01-22  7:55     ` Krzysztof Kozlowski
2024-01-22 14:48     ` Ziyang Huang
2024-01-22 14:48       ` Ziyang Huang
2024-01-21 12:42 ` [PATCH 6/8] net: mdio: ipq4019: support reset control Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-21 16:35   ` Andrew Lunn
2024-01-21 16:35     ` Andrew Lunn
2024-01-22 15:52     ` Ziyang Huang
2024-01-22 15:52       ` Ziyang Huang
2024-01-21 12:42 ` [PATCH 7/8] arm64: dts: qcom: ipq5018: enable ethernet support Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-21 16:45   ` Andrew Lunn
2024-01-21 16:45     ` Andrew Lunn
2024-01-22 15:52     ` Ziyang Huang
2024-01-22 15:52       ` Ziyang Huang
2024-01-22 17:27       ` Andrew Lunn
2024-01-22 17:27         ` Andrew Lunn
2024-01-21 12:42 ` [PATCH 8/8] arm64: dts: qcom: ipq5018-rdp432-c2: " Ziyang Huang
2024-01-21 12:42   ` Ziyang Huang
2024-01-22  7:54   ` Krzysztof Kozlowski
2024-01-22  7:54     ` Krzysztof Kozlowski
2024-01-24  0:53   ` kernel test robot
2024-01-24  0:53     ` kernel test robot
2024-01-21 15:51 ` [PATCH 0/8] ipq5018: " Andrew Lunn
2024-01-21 15:51   ` Andrew Lunn
2024-01-22 14:45   ` Ziyang Huang
2024-01-22 14:45     ` Ziyang Huang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=TYZPR01MB5556DEA3D4740441EC561414C9762@TYZPR01MB5556.apcprd01.prod.exchangelabs.com \
    --to=hzyitc@outlook.com \
    --cc=absahu@codeaurora.org \
    --cc=alexandre.torgue@foss.st.com \
    --cc=angelogioacchino.delregno@collabora.com \
    --cc=ipkumar@codeaurora.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mediatek@lists.infradead.org \
    --cc=linux-stm32@st-md-mailman.stormreply.com \
    --cc=matthias.bgg@gmail.com \
    --cc=mcoquelin.stm32@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=p.zabel@pengutronix.de \
    --cc=richardcochran@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.