From: Robert Marko Date: Thu, 8 May 2025 11:27:08 +0000 (+0200) Subject: qualcommax: use upstreamed multiple conf clock patches X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cc50cac8a0fd0e12fc9e2a7fa7d14f99a2a5ffae;p=thirdparty%2Fopenwrt.git 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 --- 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 00000000000..937e6446266 --- /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 +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 +Acked-by: Stephen Boyd +Link: https://lore.kernel.org/r/20231220221724.3822-2-ansuelsmth@gmail.com +Signed-off-by: Bjorn Andersson +--- + 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 00000000000..478f60ed44c --- /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 +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 +Signed-off-by: Christian Marangi +Acked-by: Stephen Boyd +Link: https://lore.kernel.org/r/20231220221724.3822-3-ansuelsmth@gmail.com +Signed-off-by: Bjorn Andersson +--- + 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 00000000000..5360771df22 --- /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 +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 +Acked-by: Stephen Boyd +Link: https://lore.kernel.org/r/20231220221724.3822-4-ansuelsmth@gmail.com +Signed-off-by: Bjorn Andersson +--- + 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 54d16ba9f55..00000000000 --- 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 -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 -Signed-off-by: Christian Marangi ---- - 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 - #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 2f915e2a29f..00000000000 --- 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 -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 # ipq8074 Qnap QHora-301W -Signed-off-by: Christian Marangi ---- - 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), - { }