[openwrt/openwrt] qualcommax: use upstreamed multiple conf clock patches

LEDE Commits lede-commits at lists.infradead.org
Thu May 8 04:29:05 PDT 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/cc50cac8a0fd0e12fc9e2a7fa7d14f99a2a5ffae

commit cc50cac8a0fd0e12fc9e2a7fa7d14f99a2a5ffae
Author: Robert Marko <robimarko at gmail.com>
AuthorDate: Thu May 8 13:27:08 2025 +0200

    qualcommax: use upstreamed multiple conf clock patches
    
    Multiple conf support was upstreamed into kernel 6.10, so lets use the
    upstreamed patches and mark them as so.
    
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 ...k-rcg-introduce-support-for-multiple-conf.patch |  83 ++++++
 ...k-rcg2-add-support-for-rcg2-freq-multi-op.patch | 296 +++++++++++++++++++++
 ...c-ipq8074-rework-nss_port5-6-clock-to-mul.patch | 227 ++++++++++++++++
 ...k-rcg2-introduce-support-for-multiple-con.patch | 203 --------------
 ...c-ipq8074-rework-nss_port5-6-clock-to-mul.patch | 129 ---------
 5 files changed, 606 insertions(+), 332 deletions(-)

diff --git a/target/linux/qualcommax/patches-6.6/0090-v6.10-clk-qcom-clk-rcg-introduce-support-for-multiple-conf.patch b/target/linux/qualcommax/patches-6.6/0090-v6.10-clk-qcom-clk-rcg-introduce-support-for-multiple-conf.patch
new file mode 100644
index 0000000000..937e644626
--- /dev/null
+++ b/target/linux/qualcommax/patches-6.6/0090-v6.10-clk-qcom-clk-rcg-introduce-support-for-multiple-conf.patch
@@ -0,0 +1,83 @@
+From d06b1043644a1831ab141bbee2669002bba15b0f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Wed, 20 Dec 2023 23:17:22 +0100
+Subject: [PATCH] clk: qcom: clk-rcg: introduce support for multiple conf for
+ same freq
+
+Some RCG frequency can be reached by multiple configuration.
+
+We currently declare multiple configuration for the same frequency but
+that is not supported and always the first configuration will be taken.
+
+These multiple configuration are needed as based on the current parent
+configuration, it may be needed to use a different configuration to
+reach the same frequency.
+
+To handle this introduce 3 new macro, C, FM and FMS:
+
+- C is used to declare a freq_conf where src, pre_div, m and n are
+  provided.
+
+- FM is used to declare a freq_multi_tbl with the frequency and an
+  array of confs to insert all the config for the provided frequency.
+
+- FMS is used to declare a freq_multi_tbl with the frequency and an
+  array of a single conf with the provided src, pre_div, m and n.
+
+Struct clk_rcg2 is changed to add a union type to reference a simple
+freq_tbl or a complex freq_multi_tbl.
+
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Acked-by: Stephen Boyd <sboyd at kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-2-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson at kernel.org>
+---
+ drivers/clk/qcom/clk-rcg.h | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+--- a/drivers/clk/qcom/clk-rcg.h
++++ b/drivers/clk/qcom/clk-rcg.h
+@@ -17,6 +17,23 @@ struct freq_tbl {
+ 	u16 n;
+ };
+ 
++#define C(s, h, m, n) { (s), (2 * (h) - 1), (m), (n) }
++#define FM(f, confs) { (f), ARRAY_SIZE(confs), (confs) }
++#define FMS(f, s, h, m, n) { (f), 1, (const struct freq_conf []){ C(s, h, m, n) } }
++
++struct freq_conf {
++	u8 src;
++	u8 pre_div;
++	u16 m;
++	u16 n;
++};
++
++struct freq_multi_tbl {
++	unsigned long freq;
++	size_t num_confs;
++	const struct freq_conf *confs;
++};
++
+ /**
+  * struct mn - M/N:D counter
+  * @mnctr_en_bit: bit to enable mn counter
+@@ -138,6 +155,7 @@ extern const struct clk_ops clk_dyn_rcg_
+  * @safe_src_index: safe src index value
+  * @parent_map: map from software's parent index to hardware's src_sel field
+  * @freq_tbl: frequency table
++ * @freq_multi_tbl: frequency table for clocks reachable with multiple RCGs conf
+  * @clkr: regmap clock handle
+  * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG
+  * @parked_cfg: cached value of the CFG register for parked RCGs
+@@ -149,7 +167,10 @@ struct clk_rcg2 {
+ 	u8			hid_width;
+ 	u8			safe_src_index;
+ 	const struct parent_map	*parent_map;
+-	const struct freq_tbl	*freq_tbl;
++	union {
++		const struct freq_tbl		*freq_tbl;
++		const struct freq_multi_tbl	*freq_multi_tbl;
++	};
+ 	struct clk_regmap	clkr;
+ 	u8			cfg_off;
+ 	u32			parked_cfg;
diff --git a/target/linux/qualcommax/patches-6.6/0091-v6.10-clk-qcom-clk-rcg2-add-support-for-rcg2-freq-multi-op.patch b/target/linux/qualcommax/patches-6.6/0091-v6.10-clk-qcom-clk-rcg2-add-support-for-rcg2-freq-multi-op.patch
new file mode 100644
index 0000000000..478f60ed44
--- /dev/null
+++ b/target/linux/qualcommax/patches-6.6/0091-v6.10-clk-qcom-clk-rcg2-add-support-for-rcg2-freq-multi-op.patch
@@ -0,0 +1,296 @@
+From 89da22456af0762477d8c1345fdd17961b3ada80 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Wed, 20 Dec 2023 23:17:23 +0100
+Subject: [PATCH] clk: qcom: clk-rcg2: add support for rcg2 freq multi ops
+
+Some RCG frequency can be reached by multiple configuration.
+
+Add clk_rcg2_fm_ops ops to support these special RCG configurations.
+
+These alternative ops will select the frequency using a CEIL policy.
+
+When the correct frequency is found, the correct config is selected by
+calculating the final rate (by checking the defined parent and values
+in the config that is being checked) and deciding based on the one that
+is less different than the requested one.
+
+These check are skipped if there is just one config for the requested
+freq.
+
+qcom_find_freq_multi is added to search the freq with the new struct
+freq_multi_tbl.
+__clk_rcg2_select_conf is used to select the correct conf by simulating
+the final clock.
+If a conf can't be found due to parent not reachable, a WARN is printed
+and -EINVAL is returned.
+
+Tested-by: Wei Lei <quic_leiwei at quicinc.com>
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Acked-by: Stephen Boyd <sboyd at kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-3-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson at kernel.org>
+---
+ drivers/clk/qcom/clk-rcg.h  |   1 +
+ drivers/clk/qcom/clk-rcg2.c | 166 ++++++++++++++++++++++++++++++++++++
+ drivers/clk/qcom/common.c   |  18 ++++
+ drivers/clk/qcom/common.h   |   2 +
+ 4 files changed, 187 insertions(+)
+
+--- a/drivers/clk/qcom/clk-rcg.h
++++ b/drivers/clk/qcom/clk-rcg.h
+@@ -190,6 +190,7 @@ struct clk_rcg2_gfx3d {
+ 
+ extern const struct clk_ops clk_rcg2_ops;
+ extern const struct clk_ops clk_rcg2_floor_ops;
++extern const struct clk_ops clk_rcg2_fm_ops;
+ extern const struct clk_ops clk_rcg2_mux_closest_ops;
+ extern const struct clk_ops clk_edp_pixel_ops;
+ extern const struct clk_ops clk_byte_ops;
+--- a/drivers/clk/qcom/clk-rcg2.c
++++ b/drivers/clk/qcom/clk-rcg2.c
+@@ -260,6 +260,115 @@ static int _freq_tbl_determine_rate(stru
+ 	return 0;
+ }
+ 
++static const struct freq_conf *
++__clk_rcg2_select_conf(struct clk_hw *hw, const struct freq_multi_tbl *f,
++		       unsigned long req_rate)
++{
++	unsigned long rate_diff, best_rate_diff = ULONG_MAX;
++	const struct freq_conf *conf, *best_conf = NULL;
++	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
++	const char *name = clk_hw_get_name(hw);
++	unsigned long parent_rate, rate;
++	struct clk_hw *p;
++	int index, i;
++
++	/* Exit early if only one config is defined */
++	if (f->num_confs == 1) {
++		best_conf = f->confs;
++		goto exit;
++	}
++
++	/* Search in each provided config the one that is near the wanted rate */
++	for (i = 0, conf = f->confs; i < f->num_confs; i++, conf++) {
++		index = qcom_find_src_index(hw, rcg->parent_map, conf->src);
++		if (index < 0)
++			continue;
++
++		p = clk_hw_get_parent_by_index(hw, index);
++		if (!p)
++			continue;
++
++		parent_rate =  clk_hw_get_rate(p);
++		rate = calc_rate(parent_rate, conf->n, conf->m, conf->n, conf->pre_div);
++
++		if (rate == req_rate) {
++			best_conf = conf;
++			goto exit;
++		}
++
++		rate_diff = abs_diff(req_rate, rate);
++		if (rate_diff < best_rate_diff) {
++			best_rate_diff = rate_diff;
++			best_conf = conf;
++		}
++	}
++
++	/*
++	 * Very unlikely. Warn if we couldn't find a correct config
++	 * due to parent not found in every config.
++	 */
++	if (unlikely(!best_conf)) {
++		WARN(1, "%s: can't find a configuration for rate %lu\n",
++		     name, req_rate);
++		return ERR_PTR(-EINVAL);
++	}
++
++exit:
++	return best_conf;
++}
++
++static int _freq_tbl_fm_determine_rate(struct clk_hw *hw, const struct freq_multi_tbl *f,
++				       struct clk_rate_request *req)
++{
++	unsigned long clk_flags, rate = req->rate;
++	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
++	const struct freq_conf *conf;
++	struct clk_hw *p;
++	int index;
++
++	f = qcom_find_freq_multi(f, rate);
++	if (!f || !f->confs)
++		return -EINVAL;
++
++	conf = __clk_rcg2_select_conf(hw, f, rate);
++	if (IS_ERR(conf))
++		return PTR_ERR(conf);
++	index = qcom_find_src_index(hw, rcg->parent_map, conf->src);
++	if (index < 0)
++		return index;
++
++	clk_flags = clk_hw_get_flags(hw);
++	p = clk_hw_get_parent_by_index(hw, index);
++	if (!p)
++		return -EINVAL;
++
++	if (clk_flags & CLK_SET_RATE_PARENT) {
++		rate = f->freq;
++		if (conf->pre_div) {
++			if (!rate)
++				rate = req->rate;
++			rate /= 2;
++			rate *= conf->pre_div + 1;
++		}
++
++		if (conf->n) {
++			u64 tmp = rate;
++
++			tmp = tmp * conf->n;
++			do_div(tmp, conf->m);
++			rate = tmp;
++		}
++	} else {
++		rate =  clk_hw_get_rate(p);
++	}
++
++	req->best_parent_hw = p;
++	req->best_parent_rate = rate;
++	req->rate = f->freq;
++
++	return 0;
++}
++
+ static int clk_rcg2_determine_rate(struct clk_hw *hw,
+ 				   struct clk_rate_request *req)
+ {
+@@ -276,6 +385,14 @@ static int clk_rcg2_determine_floor_rate
+ 	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, req, FLOOR);
+ }
+ 
++static int clk_rcg2_fm_determine_rate(struct clk_hw *hw,
++				      struct clk_rate_request *req)
++{
++	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
++
++	return _freq_tbl_fm_determine_rate(hw, rcg->freq_multi_tbl, req);
++}
++
+ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f,
+ 				u32 *_cfg)
+ {
+@@ -371,6 +488,30 @@ static int __clk_rcg2_set_rate(struct cl
+ 	return clk_rcg2_configure(rcg, f);
+ }
+ 
++static int __clk_rcg2_fm_set_rate(struct clk_hw *hw, unsigned long rate)
++{
++	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
++	const struct freq_multi_tbl *f;
++	const struct freq_conf *conf;
++	struct freq_tbl f_tbl = {};
++
++	f = qcom_find_freq_multi(rcg->freq_multi_tbl, rate);
++	if (!f || !f->confs)
++		return -EINVAL;
++
++	conf = __clk_rcg2_select_conf(hw, f, rate);
++	if (IS_ERR(conf))
++		return PTR_ERR(conf);
++
++	f_tbl.freq = f->freq;
++	f_tbl.src = conf->src;
++	f_tbl.pre_div = conf->pre_div;
++	f_tbl.m = conf->m;
++	f_tbl.n = conf->n;
++
++	return clk_rcg2_configure(rcg, &f_tbl);
++}
++
+ static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
+ 			    unsigned long parent_rate)
+ {
+@@ -383,6 +524,12 @@ static int clk_rcg2_set_floor_rate(struc
+ 	return __clk_rcg2_set_rate(hw, rate, FLOOR);
+ }
+ 
++static int clk_rcg2_fm_set_rate(struct clk_hw *hw, unsigned long rate,
++				unsigned long parent_rate)
++{
++	return __clk_rcg2_fm_set_rate(hw, rate);
++}
++
+ static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
+ 		unsigned long rate, unsigned long parent_rate, u8 index)
+ {
+@@ -395,6 +542,12 @@ static int clk_rcg2_set_floor_rate_and_p
+ 	return __clk_rcg2_set_rate(hw, rate, FLOOR);
+ }
+ 
++static int clk_rcg2_fm_set_rate_and_parent(struct clk_hw *hw,
++		unsigned long rate, unsigned long parent_rate, u8 index)
++{
++	return __clk_rcg2_fm_set_rate(hw, rate);
++}
++
+ static int clk_rcg2_get_duty_cycle(struct clk_hw *hw, struct clk_duty *duty)
+ {
+ 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+@@ -505,6 +658,19 @@ const struct clk_ops clk_rcg2_floor_ops
+ };
+ EXPORT_SYMBOL_GPL(clk_rcg2_floor_ops);
+ 
++const struct clk_ops clk_rcg2_fm_ops = {
++	.is_enabled = clk_rcg2_is_enabled,
++	.get_parent = clk_rcg2_get_parent,
++	.set_parent = clk_rcg2_set_parent,
++	.recalc_rate = clk_rcg2_recalc_rate,
++	.determine_rate = clk_rcg2_fm_determine_rate,
++	.set_rate = clk_rcg2_fm_set_rate,
++	.set_rate_and_parent = clk_rcg2_fm_set_rate_and_parent,
++	.get_duty_cycle = clk_rcg2_get_duty_cycle,
++	.set_duty_cycle = clk_rcg2_set_duty_cycle,
++};
++EXPORT_SYMBOL_GPL(clk_rcg2_fm_ops);
++
+ const struct clk_ops clk_rcg2_mux_closest_ops = {
+ 	.determine_rate = __clk_mux_determine_rate_closest,
+ 	.get_parent = clk_rcg2_get_parent,
+--- a/drivers/clk/qcom/common.c
++++ b/drivers/clk/qcom/common.c
+@@ -41,6 +41,24 @@ struct freq_tbl *qcom_find_freq(const st
+ }
+ EXPORT_SYMBOL_GPL(qcom_find_freq);
+ 
++const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f,
++						  unsigned long rate)
++{
++	if (!f)
++		return NULL;
++
++	if (!f->freq)
++		return f;
++
++	for (; f->freq; f++)
++		if (rate <= f->freq)
++			return f;
++
++	/* Default to our fastest rate */
++	return f - 1;
++}
++EXPORT_SYMBOL_GPL(qcom_find_freq_multi);
++
+ const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ 					    unsigned long rate)
+ {
+--- a/drivers/clk/qcom/common.h
++++ b/drivers/clk/qcom/common.h
+@@ -45,6 +45,8 @@ extern const struct freq_tbl *qcom_find_
+ 					     unsigned long rate);
+ extern const struct freq_tbl *qcom_find_freq_floor(const struct freq_tbl *f,
+ 						   unsigned long rate);
++extern const struct freq_multi_tbl *qcom_find_freq_multi(const struct freq_multi_tbl *f,
++							 unsigned long rate);
+ extern void
+ qcom_pll_set_fsm_mode(struct regmap *m, u32 reg, u8 bias_count, u8 lock_count);
+ extern int qcom_find_src_index(struct clk_hw *hw, const struct parent_map *map,
diff --git a/target/linux/qualcommax/patches-6.6/0092-v6.10-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch b/target/linux/qualcommax/patches-6.6/0092-v6.10-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch
new file mode 100644
index 0000000000..5360771df2
--- /dev/null
+++ b/target/linux/qualcommax/patches-6.6/0092-v6.10-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch
@@ -0,0 +1,227 @@
+From e88f03230dc07aa3293b6aeb078bd27370bb2594 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth at gmail.com>
+Date: Wed, 20 Dec 2023 23:17:24 +0100
+Subject: [PATCH] clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple
+ conf
+
+Rework nss_port5/6 to use the new multiple configuration implementation
+and correctly fix the clocks for these port under some corner case.
+
+This is particularly relevant for device that have 2.5G or 10G port
+connected to port5 or port 6 on ipq8074. As the parent are shared
+across multiple port it may be required to select the correct
+configuration to accomplish the desired clock. Without this patch such
+port doesn't work in some specific ethernet speed as the clock will be
+set to the wrong frequency as we just select the first configuration for
+the related frequency instead of selecting the best one.
+
+Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
+Acked-by: Stephen Boyd <sboyd at kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-4-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson at kernel.org>
+---
+ drivers/clk/qcom/gcc-ipq8074.c | 120 +++++++++++++++++++++------------
+ 1 file changed, 76 insertions(+), 44 deletions(-)
+
+--- a/drivers/clk/qcom/gcc-ipq8074.c
++++ b/drivers/clk/qcom/gcc-ipq8074.c
+@@ -1677,15 +1677,23 @@ static struct clk_regmap_div nss_port4_t
+ 	},
+ };
+ 
+-static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = {
+-	F(19200000, P_XO, 1, 0, 0),
+-	F(25000000, P_UNIPHY1_RX, 12.5, 0, 0),
+-	F(25000000, P_UNIPHY0_RX, 5, 0, 0),
+-	F(78125000, P_UNIPHY1_RX, 4, 0, 0),
+-	F(125000000, P_UNIPHY1_RX, 2.5, 0, 0),
+-	F(125000000, P_UNIPHY0_RX, 1, 0, 0),
+-	F(156250000, P_UNIPHY1_RX, 2, 0, 0),
+-	F(312500000, P_UNIPHY1_RX, 1, 0, 0),
++static const struct freq_conf ftbl_nss_port5_rx_clk_src_25[] = {
++	C(P_UNIPHY1_RX, 12.5, 0, 0),
++	C(P_UNIPHY0_RX, 5, 0, 0),
++};
++
++static const struct freq_conf ftbl_nss_port5_rx_clk_src_125[] = {
++	C(P_UNIPHY1_RX, 2.5, 0, 0),
++	C(P_UNIPHY0_RX, 1, 0, 0),
++};
++
++static const struct freq_multi_tbl ftbl_nss_port5_rx_clk_src[] = {
++	FMS(19200000, P_XO, 1, 0, 0),
++	FM(25000000, ftbl_nss_port5_rx_clk_src_25),
++	FMS(78125000, P_UNIPHY1_RX, 4, 0, 0),
++	FM(125000000, ftbl_nss_port5_rx_clk_src_125),
++	FMS(156250000, P_UNIPHY1_RX, 2, 0, 0),
++	FMS(312500000, P_UNIPHY1_RX, 1, 0, 0),
+ 	{ }
+ };
+ 
+@@ -1712,14 +1720,14 @@ gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32
+ 
+ static struct clk_rcg2 nss_port5_rx_clk_src = {
+ 	.cmd_rcgr = 0x68060,
+-	.freq_tbl = ftbl_nss_port5_rx_clk_src,
++	.freq_multi_tbl = ftbl_nss_port5_rx_clk_src,
+ 	.hid_width = 5,
+ 	.parent_map = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias_map,
+ 	.clkr.hw.init = &(struct clk_init_data){
+ 		.name = "nss_port5_rx_clk_src",
+ 		.parent_data = gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias,
+ 		.num_parents = ARRAY_SIZE(gcc_xo_uniphy0_rx_tx_uniphy1_rx_tx_ubi32_bias),
+-		.ops = &clk_rcg2_ops,
++		.ops = &clk_rcg2_fm_ops,
+ 	},
+ };
+ 
+@@ -1739,15 +1747,23 @@ static struct clk_regmap_div nss_port5_r
+ 	},
+ };
+ 
+-static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = {
+-	F(19200000, P_XO, 1, 0, 0),
+-	F(25000000, P_UNIPHY1_TX, 12.5, 0, 0),
+-	F(25000000, P_UNIPHY0_TX, 5, 0, 0),
+-	F(78125000, P_UNIPHY1_TX, 4, 0, 0),
+-	F(125000000, P_UNIPHY1_TX, 2.5, 0, 0),
+-	F(125000000, P_UNIPHY0_TX, 1, 0, 0),
+-	F(156250000, P_UNIPHY1_TX, 2, 0, 0),
+-	F(312500000, P_UNIPHY1_TX, 1, 0, 0),
++static const struct freq_conf ftbl_nss_port5_tx_clk_src_25[] = {
++	C(P_UNIPHY1_TX, 12.5, 0, 0),
++	C(P_UNIPHY0_TX, 5, 0, 0),
++};
++
++static const struct freq_conf ftbl_nss_port5_tx_clk_src_125[] = {
++	C(P_UNIPHY1_TX, 2.5, 0, 0),
++	C(P_UNIPHY0_TX, 1, 0, 0),
++};
++
++static const struct freq_multi_tbl ftbl_nss_port5_tx_clk_src[] = {
++	FMS(19200000, P_XO, 1, 0, 0),
++	FM(25000000, ftbl_nss_port5_tx_clk_src_25),
++	FMS(78125000, P_UNIPHY1_TX, 4, 0, 0),
++	FM(125000000, ftbl_nss_port5_tx_clk_src_125),
++	FMS(156250000, P_UNIPHY1_TX, 2, 0, 0),
++	FMS(312500000, P_UNIPHY1_TX, 1, 0, 0),
+ 	{ }
+ };
+ 
+@@ -1774,14 +1790,14 @@ gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32
+ 
+ static struct clk_rcg2 nss_port5_tx_clk_src = {
+ 	.cmd_rcgr = 0x68068,
+-	.freq_tbl = ftbl_nss_port5_tx_clk_src,
++	.freq_multi_tbl = ftbl_nss_port5_tx_clk_src,
+ 	.hid_width = 5,
+ 	.parent_map = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias_map,
+ 	.clkr.hw.init = &(struct clk_init_data){
+ 		.name = "nss_port5_tx_clk_src",
+ 		.parent_data = gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias,
+ 		.num_parents = ARRAY_SIZE(gcc_xo_uniphy0_tx_rx_uniphy1_tx_rx_ubi32_bias),
+-		.ops = &clk_rcg2_ops,
++		.ops = &clk_rcg2_fm_ops,
+ 	},
+ };
+ 
+@@ -1801,15 +1817,23 @@ static struct clk_regmap_div nss_port5_t
+ 	},
+ };
+ 
+-static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = {
+-	F(19200000, P_XO, 1, 0, 0),
+-	F(25000000, P_UNIPHY2_RX, 5, 0, 0),
+-	F(25000000, P_UNIPHY2_RX, 12.5, 0, 0),
+-	F(78125000, P_UNIPHY2_RX, 4, 0, 0),
+-	F(125000000, P_UNIPHY2_RX, 1, 0, 0),
+-	F(125000000, P_UNIPHY2_RX, 2.5, 0, 0),
+-	F(156250000, P_UNIPHY2_RX, 2, 0, 0),
+-	F(312500000, P_UNIPHY2_RX, 1, 0, 0),
++static const struct freq_conf ftbl_nss_port6_rx_clk_src_25[] = {
++	C(P_UNIPHY2_RX, 5, 0, 0),
++	C(P_UNIPHY2_RX, 12.5, 0, 0),
++};
++
++static const struct freq_conf ftbl_nss_port6_rx_clk_src_125[] = {
++	C(P_UNIPHY2_RX, 1, 0, 0),
++	C(P_UNIPHY2_RX, 2.5, 0, 0),
++};
++
++static const struct freq_multi_tbl ftbl_nss_port6_rx_clk_src[] = {
++	FMS(19200000, P_XO, 1, 0, 0),
++	FM(25000000, ftbl_nss_port6_rx_clk_src_25),
++	FMS(78125000, P_UNIPHY2_RX, 4, 0, 0),
++	FM(125000000, ftbl_nss_port6_rx_clk_src_125),
++	FMS(156250000, P_UNIPHY2_RX, 2, 0, 0),
++	FMS(312500000, P_UNIPHY2_RX, 1, 0, 0),
+ 	{ }
+ };
+ 
+@@ -1831,14 +1855,14 @@ static const struct parent_map gcc_xo_un
+ 
+ static struct clk_rcg2 nss_port6_rx_clk_src = {
+ 	.cmd_rcgr = 0x68070,
+-	.freq_tbl = ftbl_nss_port6_rx_clk_src,
++	.freq_multi_tbl = ftbl_nss_port6_rx_clk_src,
+ 	.hid_width = 5,
+ 	.parent_map = gcc_xo_uniphy2_rx_tx_ubi32_bias_map,
+ 	.clkr.hw.init = &(struct clk_init_data){
+ 		.name = "nss_port6_rx_clk_src",
+ 		.parent_data = gcc_xo_uniphy2_rx_tx_ubi32_bias,
+ 		.num_parents = ARRAY_SIZE(gcc_xo_uniphy2_rx_tx_ubi32_bias),
+-		.ops = &clk_rcg2_ops,
++		.ops = &clk_rcg2_fm_ops,
+ 	},
+ };
+ 
+@@ -1858,15 +1882,23 @@ static struct clk_regmap_div nss_port6_r
+ 	},
+ };
+ 
+-static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = {
+-	F(19200000, P_XO, 1, 0, 0),
+-	F(25000000, P_UNIPHY2_TX, 5, 0, 0),
+-	F(25000000, P_UNIPHY2_TX, 12.5, 0, 0),
+-	F(78125000, P_UNIPHY2_TX, 4, 0, 0),
+-	F(125000000, P_UNIPHY2_TX, 1, 0, 0),
+-	F(125000000, P_UNIPHY2_TX, 2.5, 0, 0),
+-	F(156250000, P_UNIPHY2_TX, 2, 0, 0),
+-	F(312500000, P_UNIPHY2_TX, 1, 0, 0),
++static const struct freq_conf ftbl_nss_port6_tx_clk_src_25[] = {
++	C(P_UNIPHY2_TX, 5, 0, 0),
++	C(P_UNIPHY2_TX, 12.5, 0, 0),
++};
++
++static const struct freq_conf ftbl_nss_port6_tx_clk_src_125[] = {
++	C(P_UNIPHY2_TX, 1, 0, 0),
++	C(P_UNIPHY2_TX, 2.5, 0, 0),
++};
++
++static const struct freq_multi_tbl ftbl_nss_port6_tx_clk_src[] = {
++	FMS(19200000, P_XO, 1, 0, 0),
++	FM(25000000, ftbl_nss_port6_tx_clk_src_25),
++	FMS(78125000, P_UNIPHY1_RX, 4, 0, 0),
++	FM(125000000, ftbl_nss_port6_tx_clk_src_125),
++	FMS(156250000, P_UNIPHY1_RX, 2, 0, 0),
++	FMS(312500000, P_UNIPHY1_RX, 1, 0, 0),
+ 	{ }
+ };
+ 
+@@ -1888,14 +1920,14 @@ static const struct parent_map gcc_xo_un
+ 
+ static struct clk_rcg2 nss_port6_tx_clk_src = {
+ 	.cmd_rcgr = 0x68078,
+-	.freq_tbl = ftbl_nss_port6_tx_clk_src,
++	.freq_multi_tbl = ftbl_nss_port6_tx_clk_src,
+ 	.hid_width = 5,
+ 	.parent_map = gcc_xo_uniphy2_tx_rx_ubi32_bias_map,
+ 	.clkr.hw.init = &(struct clk_init_data){
+ 		.name = "nss_port6_tx_clk_src",
+ 		.parent_data = gcc_xo_uniphy2_tx_rx_ubi32_bias,
+ 		.num_parents = ARRAY_SIZE(gcc_xo_uniphy2_tx_rx_ubi32_bias),
+-		.ops = &clk_rcg2_ops,
++		.ops = &clk_rcg2_fm_ops,
+ 	},
+ };
+ 
diff --git a/target/linux/qualcommax/patches-6.6/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch b/target/linux/qualcommax/patches-6.6/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch
deleted file mode 100644
index 54d16ba9f5..0000000000
--- a/target/linux/qualcommax/patches-6.6/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch
+++ /dev/null
@@ -1,203 +0,0 @@
-From 032be4f49dda786fea9e1501212f6cd09a7ded96 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth at gmail.com>
-Date: Thu, 3 Nov 2022 14:49:43 +0100
-Subject: [PATCH] clk: qcom: clk-rcg2: introduce support for multiple conf for
- same freq
-
-Some RCG frequency can be reached by multiple configuration.
-
-We currently declare multiple configuration for the same frequency but
-that is not supported and always the first configuration will be taken.
-
-These multiple configuration are needed as based on the current parent
-configuration, it may be needed to use a different configuration to
-reach the same frequency.
-
-To handle this introduce 2 new macro, FM and C.
-
-- FM is used to declare an empty freq_tbl with just the frequency and an
-  array of confs to insert all the config for the provided frequency.
-
-- C is used to declare a fre_conf where src, pre_div, m and n are
-  provided.
-
-The driver is changed to handle this special freq_tbl and select the
-correct config by calculating the final rate and deciding based on the
-one that is less different than the requested one.
-
-Tested-by: Robert Marko <robimarko at gmail.com>
-Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
----
- drivers/clk/qcom/clk-rcg.h  | 14 ++++++-
- drivers/clk/qcom/clk-rcg2.c | 84 +++++++++++++++++++++++++++++++++----
- 2 files changed, 88 insertions(+), 10 deletions(-)
-
---- a/drivers/clk/qcom/clk-rcg.h
-+++ b/drivers/clk/qcom/clk-rcg.h
-@@ -7,7 +7,17 @@
- #include <linux/clk-provider.h>
- #include "clk-regmap.h"
- 
--#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n) }
-+#define F(f, s, h, m, n) { (f), (s), (2 * (h) - 1), (m), (n), 0, NULL }
-+
-+#define FM(_f, _confs) { .freq = (_f), .confs_num = ARRAY_SIZE(_confs), .confs = (_confs) }
-+#define C(s, h, m, n) { (s), (2 * (h) - 1), (m), (n) }
-+
-+struct freq_conf {
-+	u8 src;
-+	u8 pre_div;
-+	u16 m;
-+	u16 n;
-+};
- 
- struct freq_tbl {
- 	unsigned long freq;
-@@ -15,6 +25,8 @@ struct freq_tbl {
- 	u8 pre_div;
- 	u16 m;
- 	u16 n;
-+	int confs_num;
-+	const struct freq_conf *confs;
- };
- 
- /**
---- a/drivers/clk/qcom/clk-rcg2.c
-+++ b/drivers/clk/qcom/clk-rcg2.c
-@@ -203,11 +203,60 @@ clk_rcg2_recalc_rate(struct clk_hw *hw,
- 	return __clk_rcg2_recalc_rate(hw, parent_rate, cfg);
- }
- 
-+static void
-+clk_rcg2_select_conf(struct clk_hw *hw, struct freq_tbl *f_tbl,
-+		     const struct freq_tbl *f, unsigned long req_rate)
-+{
-+	unsigned long best_rate = 0, parent_rate, rate;
-+	const struct freq_conf *conf, *best_conf;
-+	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
-+	struct clk_hw *p;
-+	int index, i;
-+
-+	/* Search in each provided config the one that is near the wanted rate */
-+	for (i = 0, conf = f->confs; i < f->confs_num; i++, conf++) {
-+		index = qcom_find_src_index(hw, rcg->parent_map, conf->src);
-+		if (index < 0)
-+			continue;
-+
-+		p = clk_hw_get_parent_by_index(hw, index);
-+		if (!p)
-+			continue;
-+
-+		parent_rate =  clk_hw_get_rate(p);
-+		rate = calc_rate(parent_rate, conf->n, conf->m, conf->n, conf->pre_div);
-+
-+		if (rate == req_rate) {
-+			best_conf = conf;
-+			break;
-+		}
-+
-+		if (abs(req_rate - rate) < abs(best_rate - rate)) {
-+			best_rate = rate;
-+			best_conf = conf;
-+		}
-+	}
-+
-+	/*
-+	 * Very unlikely.
-+	 * Force the first conf if we can't find a correct config.
-+	 */
-+	if (unlikely(i == f->confs_num))
-+		best_conf = f->confs;
-+
-+	/* Apply the config */
-+	f_tbl->src = best_conf->src;
-+	f_tbl->pre_div = best_conf->pre_div;
-+	f_tbl->m = best_conf->m;
-+	f_tbl->n = best_conf->n;
-+}
-+
- 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 freq_tbl f_tbl;
- 	struct clk_hw *p;
- 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- 	int index;
-@@ -226,7 +275,15 @@ static int _freq_tbl_determine_rate(stru
- 	if (!f)
- 		return -EINVAL;
- 
--	index = qcom_find_src_index(hw, rcg->parent_map, f->src);
-+	f_tbl = *f;
-+	/*
-+	 * A single freq may be reached by multiple configuration.
-+	 * Try to find the bast one if we have this kind of freq_table.
-+	 */
-+	if (f->confs)
-+		clk_rcg2_select_conf(hw, &f_tbl, f, rate);
-+
-+	index = qcom_find_src_index(hw, rcg->parent_map, f_tbl.src);
- 	if (index < 0)
- 		return index;
- 
-@@ -236,18 +293,18 @@ static int _freq_tbl_determine_rate(stru
- 		return -EINVAL;
- 
- 	if (clk_flags & CLK_SET_RATE_PARENT) {
--		rate = f->freq;
--		if (f->pre_div) {
-+		rate = f_tbl.freq;
-+		if (f_tbl.pre_div) {
- 			if (!rate)
- 				rate = req->rate;
- 			rate /= 2;
--			rate *= f->pre_div + 1;
-+			rate *= f_tbl.pre_div + 1;
- 		}
- 
--		if (f->n) {
-+		if (f_tbl.n) {
- 			u64 tmp = rate;
--			tmp = tmp * f->n;
--			do_div(tmp, f->m);
-+			tmp = tmp * f_tbl.n;
-+			do_div(tmp, f_tbl.m);
- 			rate = tmp;
- 		}
- 	} else {
-@@ -255,7 +312,7 @@ static int _freq_tbl_determine_rate(stru
- 	}
- 	req->best_parent_hw = p;
- 	req->best_parent_rate = rate;
--	req->rate = f->freq;
-+	req->rate = f_tbl.freq;
- 
- 	return 0;
- }
-@@ -353,6 +410,7 @@ static int __clk_rcg2_set_rate(struct cl
- {
- 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
- 	const struct freq_tbl *f;
-+	struct freq_tbl f_tbl;
- 
- 	switch (policy) {
- 	case FLOOR:
-@@ -368,7 +426,15 @@ static int __clk_rcg2_set_rate(struct cl
- 	if (!f)
- 		return -EINVAL;
- 
--	return clk_rcg2_configure(rcg, f);
-+	f_tbl = *f;
-+	/*
-+	 * A single freq may be reached by multiple configuration.
-+	 * Try to find the best one if we have this kind of freq_table.
-+	 */
-+	if (f->confs)
-+		clk_rcg2_select_conf(hw, &f_tbl, f, rate);
-+
-+	return clk_rcg2_configure(rcg, &f_tbl);
- }
- 
- static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
diff --git a/target/linux/qualcommax/patches-6.6/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch b/target/linux/qualcommax/patches-6.6/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch
deleted file mode 100644
index 2f915e2a29..0000000000
--- a/target/linux/qualcommax/patches-6.6/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-From f778553f296792f4d1e8b3552603ad6116ea3eb3 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth at gmail.com>
-Date: Thu, 3 Nov 2022 14:49:44 +0100
-Subject: [PATCH] clk: qcom: gcc-ipq8074: rework nss_port5/6 clock to multiple
- conf
-
-Rework nss_port5/6 to use the new multiple configuration implementation
-and correctly fix the clocks for these port under some corner case.
-
-This is particularly relevant for device that have 2.5G or 10G port
-connected to port5 or port 6 on ipq8074. As the parent are shared
-across multiple port it may be required to select the correct
-configuration to accomplish the desired clock. Without this patch such
-port doesn't work in some specific ethernet speed as the clock will be
-set to the wrong frequency as we just select the first configuration for
-the related frequency instead of selecting the best one.
-
-Tested-by: Robert Marko <robimarko at gmail.com> # ipq8074 Qnap QHora-301W
-Signed-off-by: Christian Marangi <ansuelsmth at gmail.com>
----
- drivers/clk/qcom/gcc-ipq8074.c | 64 +++++++++++++++++++++++++---------
- 1 file changed, 48 insertions(+), 16 deletions(-)
-
---- a/drivers/clk/qcom/gcc-ipq8074.c
-+++ b/drivers/clk/qcom/gcc-ipq8074.c
-@@ -1677,13 +1677,21 @@ static struct clk_regmap_div nss_port4_t
- 	},
- };
- 
-+static const struct freq_conf ftbl_nss_port5_rx_clk_src_25[] = {
-+	C(P_UNIPHY1_RX, 12.5, 0, 0),
-+	C(P_UNIPHY0_RX, 5, 0, 0),
-+};
-+
-+static const struct freq_conf ftbl_nss_port5_rx_clk_src_125[] = {
-+	C(P_UNIPHY1_RX, 2.5, 0, 0),
-+	C(P_UNIPHY0_RX, 1, 0, 0),
-+};
-+
- static const struct freq_tbl ftbl_nss_port5_rx_clk_src[] = {
- 	F(19200000, P_XO, 1, 0, 0),
--	F(25000000, P_UNIPHY1_RX, 12.5, 0, 0),
--	F(25000000, P_UNIPHY0_RX, 5, 0, 0),
-+	FM(25000000, ftbl_nss_port5_rx_clk_src_25),
- 	F(78125000, P_UNIPHY1_RX, 4, 0, 0),
--	F(125000000, P_UNIPHY1_RX, 2.5, 0, 0),
--	F(125000000, P_UNIPHY0_RX, 1, 0, 0),
-+	FM(125000000, ftbl_nss_port5_rx_clk_src_125),
- 	F(156250000, P_UNIPHY1_RX, 2, 0, 0),
- 	F(312500000, P_UNIPHY1_RX, 1, 0, 0),
- 	{ }
-@@ -1739,13 +1747,21 @@ static struct clk_regmap_div nss_port5_r
- 	},
- };
- 
-+static struct freq_conf ftbl_nss_port5_tx_clk_src_25[] = {
-+	C(P_UNIPHY1_TX, 12.5, 0, 0),
-+	C(P_UNIPHY0_TX, 5, 0, 0),
-+};
-+
-+static struct freq_conf ftbl_nss_port5_tx_clk_src_125[] = {
-+	C(P_UNIPHY1_TX, 2.5, 0, 0),
-+	C(P_UNIPHY0_TX, 1, 0, 0),
-+};
-+
- static const struct freq_tbl ftbl_nss_port5_tx_clk_src[] = {
- 	F(19200000, P_XO, 1, 0, 0),
--	F(25000000, P_UNIPHY1_TX, 12.5, 0, 0),
--	F(25000000, P_UNIPHY0_TX, 5, 0, 0),
-+	FM(25000000, ftbl_nss_port5_tx_clk_src_25),
- 	F(78125000, P_UNIPHY1_TX, 4, 0, 0),
--	F(125000000, P_UNIPHY1_TX, 2.5, 0, 0),
--	F(125000000, P_UNIPHY0_TX, 1, 0, 0),
-+	FM(125000000, ftbl_nss_port5_tx_clk_src_125),
- 	F(156250000, P_UNIPHY1_TX, 2, 0, 0),
- 	F(312500000, P_UNIPHY1_TX, 1, 0, 0),
- 	{ }
-@@ -1801,13 +1817,21 @@ static struct clk_regmap_div nss_port5_t
- 	},
- };
- 
-+static struct freq_conf ftbl_nss_port6_rx_clk_src_25[] = {
-+	C(P_UNIPHY2_RX, 5, 0, 0),
-+	C(P_UNIPHY2_RX, 12.5, 0, 0),
-+};
-+
-+static struct freq_conf ftbl_nss_port6_rx_clk_src_125[] = {
-+	C(P_UNIPHY2_RX, 1, 0, 0),
-+	C(P_UNIPHY2_RX, 2.5, 0, 0),
-+};
-+
- static const struct freq_tbl ftbl_nss_port6_rx_clk_src[] = {
- 	F(19200000, P_XO, 1, 0, 0),
--	F(25000000, P_UNIPHY2_RX, 5, 0, 0),
--	F(25000000, P_UNIPHY2_RX, 12.5, 0, 0),
-+	FM(25000000, ftbl_nss_port6_rx_clk_src_25),
- 	F(78125000, P_UNIPHY2_RX, 4, 0, 0),
--	F(125000000, P_UNIPHY2_RX, 1, 0, 0),
--	F(125000000, P_UNIPHY2_RX, 2.5, 0, 0),
-+	FM(125000000, ftbl_nss_port6_rx_clk_src_125),
- 	F(156250000, P_UNIPHY2_RX, 2, 0, 0),
- 	F(312500000, P_UNIPHY2_RX, 1, 0, 0),
- 	{ }
-@@ -1858,13 +1882,21 @@ static struct clk_regmap_div nss_port6_r
- 	},
- };
- 
-+static struct freq_conf ftbl_nss_port6_tx_clk_src_25[] = {
-+	C(P_UNIPHY2_TX, 5, 0, 0),
-+	C(P_UNIPHY2_TX, 12.5, 0, 0),
-+};
-+
-+static struct freq_conf ftbl_nss_port6_tx_clk_src_125[] = {
-+	C(P_UNIPHY2_TX, 1, 0, 0),
-+	C(P_UNIPHY2_TX, 2.5, 0, 0),
-+};
-+
- static const struct freq_tbl ftbl_nss_port6_tx_clk_src[] = {
- 	F(19200000, P_XO, 1, 0, 0),
--	F(25000000, P_UNIPHY2_TX, 5, 0, 0),
--	F(25000000, P_UNIPHY2_TX, 12.5, 0, 0),
-+	FM(25000000, ftbl_nss_port6_tx_clk_src_25),
- 	F(78125000, P_UNIPHY2_TX, 4, 0, 0),
--	F(125000000, P_UNIPHY2_TX, 1, 0, 0),
--	F(125000000, P_UNIPHY2_TX, 2.5, 0, 0),
-+	FM(125000000, ftbl_nss_port6_tx_clk_src_125),
- 	F(156250000, P_UNIPHY2_TX, 2, 0, 0),
- 	F(312500000, P_UNIPHY2_TX, 1, 0, 0),
- 	{ }




More information about the lede-commits mailing list