[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