]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
qualcommax: use upstreamed multiple conf clock patches
authorRobert Marko <robimarko@gmail.com>
Thu, 8 May 2025 11:27:08 +0000 (13:27 +0200)
committerRobert Marko <robimarko@gmail.com>
Thu, 8 May 2025 11:28:52 +0000 (13:28 +0200)
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@gmail.com>
target/linux/qualcommax/patches-6.6/0090-v6.10-clk-qcom-clk-rcg-introduce-support-for-multiple-conf.patch [new file with mode: 0644]
target/linux/qualcommax/patches-6.6/0091-v6.10-clk-qcom-clk-rcg2-add-support-for-rcg2-freq-multi-op.patch [new file with mode: 0644]
target/linux/qualcommax/patches-6.6/0092-v6.10-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch [new file with mode: 0644]
target/linux/qualcommax/patches-6.6/0100-clk-qcom-clk-rcg2-introduce-support-for-multiple-con.patch [deleted file]
target/linux/qualcommax/patches-6.6/0101-clk-qcom-gcc-ipq8074-rework-nss_port5-6-clock-to-mul.patch [deleted file]

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 (file)
index 0000000..937e644
--- /dev/null
@@ -0,0 +1,83 @@
+From d06b1043644a1831ab141bbee2669002bba15b0f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@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@gmail.com>
+Acked-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-2-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson@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 (file)
index 0000000..478f60e
--- /dev/null
@@ -0,0 +1,296 @@
+From 89da22456af0762477d8c1345fdd17961b3ada80 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@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@quicinc.com>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Acked-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-3-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson@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 (file)
index 0000000..5360771
--- /dev/null
@@ -0,0 +1,227 @@
+From e88f03230dc07aa3293b6aeb078bd27370bb2594 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@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@gmail.com>
+Acked-by: Stephen Boyd <sboyd@kernel.org>
+Link: https://lore.kernel.org/r/20231220221724.3822-4-ansuelsmth@gmail.com
+Signed-off-by: Bjorn Andersson <andersson@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 (file)
index 54d16ba..0000000
+++ /dev/null
@@ -1,203 +0,0 @@
-From 032be4f49dda786fea9e1501212f6cd09a7ded96 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@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@gmail.com>
-Signed-off-by: Christian Marangi <ansuelsmth@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 (file)
index 2f915e2..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-From f778553f296792f4d1e8b3552603ad6116ea3eb3 Mon Sep 17 00:00:00 2001
-From: Christian Marangi <ansuelsmth@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@gmail.com> # ipq8074 Qnap QHora-301W
-Signed-off-by: Christian Marangi <ansuelsmth@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),
-       { }