From 3866b02cf82c1edb23b33e52e98475c5b3ef67d1 Mon Sep 17 00:00:00 2001 From: Chetan C R Date: Wed, 27 Apr 2022 21:56:17 +0530 Subject: [PATCH 01/14] clk: qcom: clk-alpha-pll: Add support for FSM legacy mode The Lucid PLL could require the FSM legacy mode bit to be set for the PLL to be operational, thus add support and set the same when the flag is set. Change-Id: I3ed4b6c38a1769c5021f17e0115215eab615ab62 Signed-off-by: Taniya Das Signed-off-by: Chetan C R --- drivers/clk/qcom/clk-alpha-pll.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 9b12b174da48..cc0087f09551 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1848,6 +1848,10 @@ void clk_trion_pll_configure(struct clk_alpha_pll *pll, struct regmap *regmap, regmap_update_bits(regmap, PLL_MODE(pll), PLL_UPDATE_BYPASS, PLL_UPDATE_BYPASS); + if (pll->flags & SUPPORTS_FSM_LEGACY_MODE) + regmap_update_bits(regmap, PLL_MODE(pll), PLL_FSM_LEGACY_MODE, + PLL_FSM_LEGACY_MODE); + /* Disable PLL output */ regmap_update_bits(regmap, PLL_MODE(pll), PLL_OUTCTRL, 0); From 26dd7a20482d1d7a7f93fd62f9c2d06e69c43a5f Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Fri, 18 Mar 2022 10:08:56 -0700 Subject: [PATCH 02/14] clk: qcom: gdsc-regulator: use cfg-gdscr for hw-ctrl-addr property If cfg-gdscr property is defined then use cfg-gdscr register POWER_UP/DOWN_COMPLETE status for hw-ctrl gdscr on/off polling. Change-Id: I5a217048cc3ab8106f5a7049c7bed153163a2de1 Signed-off-by: Vivek Aknurwar --- drivers/clk/qcom/gdsc-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c index 60f4b7695a47..3680a801b02c 100644 --- a/drivers/clk/qcom/gdsc-regulator.c +++ b/drivers/clk/qcom/gdsc-regulator.c @@ -121,7 +121,7 @@ static int poll_gdsc_status(struct gdsc *sc, enum gdscr_status status) int count = sc->gds_timeout; u32 val, reg_offset; - if (sc->hw_ctrl) + if (sc->hw_ctrl && !sc->cfg_gdscr) regmap = sc->hw_ctrl; else regmap = sc->regmap; From 0fd73c1d3c6f71285e4cf4a5c141710e1c4576e7 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Sat, 2 Jul 2022 09:47:23 +0530 Subject: [PATCH 03/14] clk: qcom: branch: Add BRANCH_HALT_INVERT flag support for branch clocks Add the BRANCH_HALT_INVERT flag to handle the inverted status bit check for branch clocks. Invert branch halt would indicate the clock ON when CLK_OFF bit is '1' and OFF when CLK_OFF bit is '0'. Change-Id: Ic6629e8d9548629d5d4988b3ee89a092600d610e Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-branch.c | 5 +++++ drivers/clk/qcom/clk-branch.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 4f967084137e..8eaaed476c26 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013, 2016, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -61,6 +62,10 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) if (enabling) { val &= mask; + + if (br->halt_check == BRANCH_HALT_INVERT) + return (val & BRANCH_CLK_OFF) == BRANCH_CLK_OFF; + return (val & BRANCH_CLK_OFF) == 0 || val == BRANCH_NOC_FSM_STATUS_ON; } else { diff --git a/drivers/clk/qcom/clk-branch.h b/drivers/clk/qcom/clk-branch.h index 2657c0ab7486..da471d6f4eb6 100644 --- a/drivers/clk/qcom/clk-branch.h +++ b/drivers/clk/qcom/clk-branch.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* Copyright (c) 2013, 2016, 2020 The Linux Foundation. All rights reserved. */ +/* Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #ifndef __QCOM_CLK_BRANCH_H__ #define __QCOM_CLK_BRANCH_H__ @@ -36,6 +37,7 @@ struct clk_branch { #define BRANCH_HALT_ENABLE_VOTED (BRANCH_HALT_ENABLE | BRANCH_VOTED) #define BRANCH_HALT_DELAY 2 /* No bit to check; just delay */ #define BRANCH_HALT_SKIP 3 /* Don't check halt bit */ +#define BRANCH_HALT_INVERT 4 /* Invert logic for halt bit */ struct clk_regmap clkr; }; From 6f6c0c5b1bfbf31a101558d22ba862365ca38af0 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Wed, 25 May 2022 12:06:39 +0530 Subject: [PATCH 04/14] clk: qcom: common: Fix clk_debug_init failure Remove subsys_initcall trigger for clk_debug_init(), as root clk debugfs directory is not ready by that time. And make sure that clk_debug_init() is called after the clk framework's clk_debug_init(). Change-Id: Ie90b89e4156e7f5631e9e58316534bf806012853 Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-debug.c | 5 +++++ drivers/clk/qcom/common.c | 7 +------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index 80fd26e84565..285d80a083ad 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -25,6 +25,7 @@ static struct clk_hw *measure; static bool debug_suspend; static bool debug_suspend_atomic; +static bool qcom_clk_debug_inited; static struct dentry *clk_debugfs_suspend; static struct dentry *clk_debugfs_suspend_atomic; @@ -765,6 +766,10 @@ void clk_common_debug_init(struct clk_hw *hw, struct dentry *dentry) debugfs_create_file("clk_print_regs", 0444, dentry, hw, &clock_print_hw_fops); + if (!qcom_clk_debug_inited) { + clk_debug_init(); + qcom_clk_debug_inited = true; + } } static int clk_list_rate_vdd_level(struct clk_hw *hw, unsigned int rate) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index a45119c50b80..88cce2535199 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -2,6 +2,7 @@ /* * Copyright (c) 2013-2014, 2017-2021, The Linux Foundation. * All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -589,12 +590,6 @@ int qcom_cc_runtime_suspend(struct device *dev) } EXPORT_SYMBOL(qcom_cc_runtime_suspend); -static int __init qcom_clk_init(void) -{ - return clk_debug_init(); -} -subsys_initcall(qcom_clk_init); - static void __exit qcom_clk_exit(void) { clk_debug_exit(); From aa899c2d1fa31e247f04810f125ac9c60927c901 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Wed, 27 Jul 2022 12:02:44 -0700 Subject: [PATCH 05/14] clk: qcom: Calculate branch/RCG timeouts based on frequency Clocks with extremely low rates (i.e. 10s of Hz) take much longer to enable, disable, or change rates than our current timeouts allow. Instead of increasing the timeouts to huge values for all clocks, dynamically compute the required timeouts based on the configured clock rates. Change-Id: I122ace891c2246763f9fe6da8df2c4a4307ba42d Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-branch.c | 24 ++++++++++++++++++++---- drivers/clk/qcom/clk-rcg.h | 1 + drivers/clk/qcom/clk-rcg2.c | 27 ++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 7 deletions(-) diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c index 8eaaed476c26..d19bb2e7f5bb 100644 --- a/drivers/clk/qcom/clk-branch.c +++ b/drivers/clk/qcom/clk-branch.c @@ -73,9 +73,25 @@ static bool clk_branch2_check_halt(const struct clk_branch *br, bool enabling) } } +static int get_branch_timeout(const struct clk_branch *br) +{ + int rate, period_us, timeout; + + /* + * The time it takes a clock branch to toggle is roughly 3 clock cycles. + */ + rate = clk_hw_get_rate(&br->clkr.hw); + period_us = 1000000 / rate; + timeout = 3 * period_us; + + return max(timeout, 200); +} + static int clk_branch_wait(const struct clk_branch *br, bool enabling, bool (check_halt)(const struct clk_branch *, bool)) { + int timeout, count; + bool voted = br->halt_check & BRANCH_VOTED; /* * Skip checking halt bit if we're explicitly ignoring the bit or the @@ -89,15 +105,15 @@ static int clk_branch_wait(const struct clk_branch *br, bool enabling, } else if (br->halt_check == BRANCH_HALT_ENABLE || br->halt_check == BRANCH_HALT || (enabling && voted)) { - int count = 200; + timeout = get_branch_timeout(br); - while (count-- > 0) { + for (count = timeout; count > 0; count--) { if (check_halt(br, enabling)) return 0; udelay(1); } - WARN_CLK((struct clk_hw *)&br->clkr.hw, 1, "status stuck at 'o%s'", - enabling ? "ff" : "n"); + WARN_CLK((struct clk_hw *)&br->clkr.hw, 1, "status stuck at 'o%s' after %d us", + enabling ? "ff" : "n", timeout); return -EBUSY; } return 0; diff --git a/drivers/clk/qcom/clk-rcg.h b/drivers/clk/qcom/clk-rcg.h index fa1e8533ba35..e3f68354e85b 100644 --- a/drivers/clk/qcom/clk-rcg.h +++ b/drivers/clk/qcom/clk-rcg.h @@ -154,6 +154,7 @@ struct clk_rcg2 { u8 safe_src_index; const struct parent_map *parent_map; const struct freq_tbl *freq_tbl; + unsigned long configured_freq; unsigned long current_freq; bool enable_safe_config; struct clk_regmap clkr; diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index ca1bb000a3af..6c6d2c4e965d 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2013, 2016-2018, 2020-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -118,9 +119,25 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw) return __clk_rcg2_get_parent(hw, cfg); } +static int get_update_timeout(const struct clk_rcg2 *rcg) +{ + int timeout = 0; + + /* + * The time it takes an RCG to update is roughly 3 clock cycles of the + * old and new clock rates. + */ + if (rcg->current_freq) + timeout += 3 * (1000000 / rcg->current_freq); + if (rcg->configured_freq) + timeout += 3 * (1000000 / rcg->configured_freq); + + return max(timeout, 500); +} + static int update_config(struct clk_rcg2 *rcg) { - int count, ret; + int timeout, count, ret; u32 cmd; struct clk_hw *hw = &rcg->clkr.hw; @@ -129,8 +146,10 @@ static int update_config(struct clk_rcg2 *rcg) if (ret) return ret; + timeout = get_update_timeout(rcg); + /* Wait for update to take effect */ - for (count = 500; count > 0; count--) { + for (count = timeout; count > 0; count--) { ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd); if (ret) return ret; @@ -139,7 +158,7 @@ static int update_config(struct clk_rcg2 *rcg) udelay(1); } - WARN_CLK(hw, 1, "rcg didn't update its configuration."); + WARN_CLK(hw, 1, "rcg didn't update its configuration after %d us.", timeout); return -EBUSY; } @@ -487,6 +506,8 @@ static int clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f) if (ret) return ret; + rcg->configured_freq = f->freq; + return update_config(rcg); } From 6497e33a15fd49d558b484cb7e8991fe0062377f Mon Sep 17 00:00:00 2001 From: Kalpak Kawadkar Date: Mon, 13 Jun 2022 14:18:12 +0530 Subject: [PATCH 06/14] clk: qcom: clk-debug: Enable ftrace for clock frequency measurement Enable ftrace support for clocks so that clients can measure frequency of the clock through ftraces. Change-Id: Ie923ac538b670598bb1be009e892a68c4f1e2a38 Signed-off-by: Kalpak Kawadkar --- drivers/clk/qcom/clk-debug.c | 2 ++ drivers/clk/qcom/trace.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index 285d80a083ad..ef744047079f 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -480,6 +480,8 @@ static int clk_debug_measure_get(void *data, u64 *val) *val *= get_mux_divs(measure); disable_debug_clks(measure); } + + trace_clk_measure(clk_hw_get_name(hw), *val); exit: mutex_unlock(&clk_debug_lock); clk_runtime_put_debug_mux(meas); diff --git a/drivers/clk/qcom/trace.h b/drivers/clk/qcom/trace.h index a95d8076cd74..9fa5d24f53ff 100644 --- a/drivers/clk/qcom/trace.h +++ b/drivers/clk/qcom/trace.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only * * Copyright (c) 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. */ #undef TRACE_SYSTEM @@ -47,6 +48,33 @@ DEFINE_EVENT(clk_state_dump, clk_state, TP_ARGS(name, prepare_count, enable_count, rate, vdd_level) ); +DECLARE_EVENT_CLASS(clk_measure_support, + + TP_PROTO(const char *name, unsigned long rate), + + TP_ARGS(name, rate), + + TP_STRUCT__entry( + __string(name, name) + __field(unsigned long, rate) + ), + + TP_fast_assign( + __assign_str(name, name); + __entry->rate = rate; + ), + + TP_printk("%s rate: %lu", + __get_str(name), (unsigned long)__entry->rate) +); + +DEFINE_EVENT(clk_measure_support, clk_measure, + + TP_PROTO(const char *name, unsigned long rate), + + TP_ARGS(name, rate) +); + #endif /* _TRACE_CLOCK_QCOM */ /* This part must be outside protection */ From cdc3459d092e015123dfae32fe79320d1479205e Mon Sep 17 00:00:00 2001 From: Xubin Bai Date: Tue, 2 Aug 2022 21:37:58 +0800 Subject: [PATCH 07/14] clk: qcom: Mark the parent's clock of critical-devices as critical MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The clocks of devices with the “qcom,critical-devices” property are marked as critical and can be enabled on default, the parent's clocks of these child critical-devices also need to be marked as critical. Rather than adding child and parent devices in the dts property "qcom,critical-devices", it's better to automatically mark the clock of parent device as critical. Change-Id: If7b0f53c45194dbc0cd41e13316101a9149a4dc8 Signed-off-by: Xubin Bai --- drivers/clk/qcom/common.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/drivers/clk/qcom/common.c b/drivers/clk/qcom/common.c index 88cce2535199..21f5c2ae2354 100644 --- a/drivers/clk/qcom/common.c +++ b/drivers/clk/qcom/common.c @@ -252,26 +252,29 @@ static void qcom_cc_set_critical(struct device *dev, struct qcom_cc *cc) } of_property_for_each_u32(dev->of_node, "qcom,critical-devices", prop, p, i) { - np = of_find_node_by_phandle(i); - if (!np) - continue; - - cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells"); - - for (i = 0; i < cnt; i++) { - of_parse_phandle_with_args(np, "clocks", "#clock-cells", - i, &args); - clock_idx = args.args[0]; - - if (args.np != dev->of_node || clock_idx >= cc->num_rclks) + for (np = of_find_node_by_phandle(i); np; np = of_get_parent(np)) { + if (!of_property_read_bool(np, "clocks")) { + of_node_put(np); continue; + } - if (cc->rclks[clock_idx]) - cc->rclks[clock_idx]->flags |= QCOM_CLK_IS_CRITICAL; - of_node_put(args.np); + cnt = of_count_phandle_with_args(np, "clocks", "#clock-cells"); + + for (i = 0; i < cnt; i++) { + of_parse_phandle_with_args(np, "clocks", "#clock-cells", + i, &args); + clock_idx = args.args[0]; + + if (args.np != dev->of_node || clock_idx >= cc->num_rclks) + continue; + + if (cc->rclks[clock_idx]) + cc->rclks[clock_idx]->flags |= QCOM_CLK_IS_CRITICAL; + of_node_put(args.np); + } + + of_node_put(np); } - - of_node_put(np); } } From 7f4eff6b2c41f501acb6c64f4be6ba822b81b1d4 Mon Sep 17 00:00:00 2001 From: Mike Tipton Date: Fri, 12 Aug 2022 12:44:05 -0700 Subject: [PATCH 08/14] clk: qcom: regmap-mux: Add list_registers for muxes Add list_registers callback for muxes so we can ensure they're configured to the expected parent in debugging scenarios. Change-Id: I85baff36e1aea88faa85a1fc470e051836919312 Signed-off-by: Mike Tipton --- drivers/clk/qcom/clk-regmap-mux.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/clk/qcom/clk-regmap-mux.c b/drivers/clk/qcom/clk-regmap-mux.c index 45d9cca28064..b0c2440ab1e7 100644 --- a/drivers/clk/qcom/clk-regmap-mux.c +++ b/drivers/clk/qcom/clk-regmap-mux.c @@ -9,6 +9,7 @@ #include #include "clk-regmap-mux.h" +#include "clk-debug.h" static inline struct clk_regmap_mux *to_clk_regmap_mux(struct clk_hw *hw) { @@ -49,9 +50,34 @@ static int mux_set_parent(struct clk_hw *hw, u8 index) return regmap_update_bits(clkr->regmap, mux->reg, mask, val); } +static void clk_regmap_mux_list_registers(struct seq_file *f, struct clk_hw *hw) +{ + struct clk_regmap_mux *mux = to_clk_regmap_mux(hw); + int val; + + regmap_read(mux->clkr.regmap, mux->reg, &val); + clock_debug_output(f, "%20s: 0x%.8x\n", "MUXR", val); +} + +static struct clk_regmap_ops clk_regmap_mux_regmap_ops = { + .list_registers = clk_regmap_mux_list_registers, +}; + +static int clk_regmap_mux_init(struct clk_hw *hw) +{ + struct clk_regmap *rclk = to_clk_regmap(hw); + + if (!rclk->ops) + rclk->ops = &clk_regmap_mux_regmap_ops; + + return 0; +} + const struct clk_ops clk_regmap_mux_closest_ops = { .get_parent = mux_get_parent, .set_parent = mux_set_parent, .determine_rate = __clk_mux_determine_rate_closest, + .init = clk_regmap_mux_init, + .debug_init = clk_common_debug_init, }; EXPORT_SYMBOL_GPL(clk_regmap_mux_closest_ops); From fb46a76de1c8472786e5269f0c7965cdbe95095f Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Wed, 17 Feb 2021 17:21:41 +0530 Subject: [PATCH 09/14] clk: qcom: clk-rcg2: Add enable & disable callbacks for RCG floor ops If enable safe config is true and a rate scaling request comes while RCG is in disabled state, RCG's new configuration update would be done as part of enabling the RCG. Hence add the enable and disable callbacks for floor ops to properly configure the RCG in all cases. Change-Id: I3621e0dd2cb948cb523cd85659d0de0359ba5829 Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/clk-rcg2.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c index 6c6d2c4e965d..782ba871e3a0 100644 --- a/drivers/clk/qcom/clk-rcg2.c +++ b/drivers/clk/qcom/clk-rcg2.c @@ -887,6 +887,8 @@ const struct clk_ops clk_rcg2_floor_ops = { .pre_rate_change = clk_pre_change_regmap, .post_rate_change = clk_post_change_regmap, .is_enabled = clk_rcg2_is_enabled, + .enable = clk_rcg2_enable, + .disable = clk_rcg2_disable, .get_parent = clk_rcg2_get_parent, .set_parent = clk_rcg2_set_parent, .recalc_rate = clk_rcg2_recalc_rate, From 8f5453b4c59c8c258ecfa1eb51784695627466f9 Mon Sep 17 00:00:00 2001 From: Madhuri Medasani Date: Tue, 31 Aug 2021 09:30:48 +0530 Subject: [PATCH 10/14] clk: qcom: clk-regmap: Update type for rate in clk prepare On 32 bit the PLL frequency can be beyond the range of the `int` leads to improper assignment, so update rate type to 'unsigned long'. Change-Id: I50f03ea95b3d934c4936087998f832373e620e46 Signed-off-by: Madhuri Medasani --- drivers/clk/qcom/clk-regmap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c index 4c0261cbcb18..a6c2e4b4bce6 100644 --- a/drivers/clk/qcom/clk-regmap.c +++ b/drivers/clk/qcom/clk-regmap.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 /* - * Copyright (c) 2014, 2019-2020 The Linux Foundation. All rights reserved. + * Copyright (c) 2014, 2019-2021 The Linux Foundation. All rights reserved. */ #include @@ -195,7 +195,7 @@ EXPORT_SYMBOL(clk_post_change_regmap); int clk_prepare_regmap(struct clk_hw *hw) { struct clk_regmap *rclk = to_clk_regmap(hw); - int rate = clk_hw_get_rate(hw); + unsigned long rate = clk_hw_get_rate(hw); int vdd_level; if (!rclk->vdd_data.rate_max) From d0154ed359c56cd3447b22f68ada6cc33ccb2e15 Mon Sep 17 00:00:00 2001 From: Jagadeesh Kona Date: Thu, 25 Aug 2022 16:28:15 +0530 Subject: [PATCH 11/14] clk: qcom: clk-debug: Remove mutex locking from trace probe callback Trace probe callbacks are called with preemption disabled and locking a mutex inside it is not allowed since it can potentially sleep. Hence remove support for mutex locking in suspend trace probe callback. The resource protected by this mutex clk_hw_debug_list is modified only during registering and deregistering clocks which won't happen during the suspend path, so it is safe to remove the mutex locking. Change-Id: I525099f8bae74808c9690abb43b2dc2da9c0fc88 Signed-off-by: Jagadeesh Kona --- drivers/clk/qcom/clk-debug.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c index ef744047079f..ffb36a69d973 100644 --- a/drivers/clk/qcom/clk-debug.c +++ b/drivers/clk/qcom/clk-debug.c @@ -966,9 +966,7 @@ static void clk_debug_suspend_trace_probe(void *unused, { if (start && val > 0 && !strcmp("machine_suspend", action)) { pr_info("Enabled Clocks:\n"); - mutex_lock(&clk_debug_lock); clock_debug_print_enabled_clocks(NULL); - mutex_unlock(&clk_debug_lock); } } From 50325a326e5096d09b2f70a80304b683f7be8be1 Mon Sep 17 00:00:00 2001 From: Veera Vegivada Date: Wed, 31 Aug 2022 22:55:27 -0700 Subject: [PATCH 12/14] clk: qcom: clk-alpha-pll: Update the list_registers ops for alpha PLL Update list_register operation to read the pll offset defined in PLL register map to avoid mismatch across various targets. Change-Id: Iab536c49a8e621c0ebd8c5fe7a43fa7aa42671b8 Signed-off-by: Veera Vegivada Signed-off-by: Dipa Mantre --- drivers/clk/qcom/clk-alpha-pll.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index cc0087f09551..25f6e8c3bd6b 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -1004,12 +1004,16 @@ static void clk_alpha_pll_list_registers(struct seq_file *f, struct clk_hw *hw) int size, i, val; static struct clk_register_data data[] = { - {"PLL_MODE", 0x0}, - {"PLL_L_VAL", 0x4}, - {"PLL_ALPHA_VAL", 0x8}, - {"PLL_ALPHA_VAL_U", 0xC}, - {"PLL_USER_CTL", 0x10}, - {"PLL_CONFIG_CTL", 0x18}, + {"PLL_MODE", PLL_OFF_MODE}, + {"PLL_L_VAL", PLL_OFF_L_VAL}, + {"PLL_ALPHA_VAL", PLL_OFF_ALPHA_VAL}, + {"PLL_ALPHA_VAL_U", PLL_OFF_ALPHA_VAL_U}, + {"PLL_TEST_CTL", PLL_OFF_TEST_CTL}, + {"PLL_TEST_CTL_U", PLL_OFF_TEST_CTL_U}, + {"PLL_USER_CTL", PLL_OFF_USER_CTL}, + {"PLL_USER_CTL_U", PLL_OFF_USER_CTL_U}, + {"PLL_CONFIG_CTL", PLL_OFF_CONFIG_CTL}, + {"PLL_STATUS", PLL_OFF_STATUS}, }; static struct clk_register_data data1[] = { @@ -1019,12 +1023,13 @@ static void clk_alpha_pll_list_registers(struct seq_file *f, struct clk_hw *hw) size = ARRAY_SIZE(data); for (i = 0; i < size; i++) { - regmap_read(pll->clkr.regmap, pll->offset + data[i].offset, - &val); + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[i].offset], &val); clock_debug_output(f, "%20s: 0x%.8x\n", data[i].name, val); } - regmap_read(pll->clkr.regmap, pll->offset + data[0].offset, &val); + regmap_read(pll->clkr.regmap, pll->offset + + pll->regs[data[0].offset], &val); if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + From 262e30a4f372701801d30ee412ffe534d0074020 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Mon, 19 Sep 2022 10:26:47 +0530 Subject: [PATCH 13/14] clk: qcom: clk-alpha-pll: Fix APSS_PLL_VOTE debug register output Fix wrongly mapped APSS_PLL_VOTE debug register output name in PLL register dump. Change-Id: I729c9d4b01d046eeb9c889f7547dafe85fd920c8 Signed-off-by: Imran Shaik --- drivers/clk/qcom/clk-alpha-pll.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/clk-alpha-pll.c b/drivers/clk/qcom/clk-alpha-pll.c index 25f6e8c3bd6b..be210738a788 100644 --- a/drivers/clk/qcom/clk-alpha-pll.c +++ b/drivers/clk/qcom/clk-alpha-pll.c @@ -2019,7 +2019,7 @@ static void lucid_pll_list_registers(struct seq_file *f, if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); - clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } @@ -2137,7 +2137,7 @@ static void clk_agera_pll_list_registers(struct seq_file *f, struct clk_hw *hw) if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); - clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } @@ -2985,7 +2985,7 @@ static void clk_regera_pll_list_registers(struct seq_file *f, struct clk_hw *hw) if (val & PLL_FSM_ENA) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); - clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } @@ -3352,7 +3352,7 @@ static void lucid_evo_pll_list_registers(struct seq_file *f, if (val & LUCID_EVO_ENABLE_VOTE_RUN) { regmap_read(pll->clkr.regmap, pll->clkr.enable_reg + data1[0].offset, &val); - clock_debug_output(f, "%20s: 0x%.8x\n", data[0].name, val); + clock_debug_output(f, "%20s: 0x%.8x\n", data1[0].name, val); } } From 85c8c38084e497142cbef7bdedfa17cb9c1c08f0 Mon Sep 17 00:00:00 2001 From: Veera Vegivada Date: Wed, 22 Jun 2022 17:47:27 +0530 Subject: [PATCH 14/14] clk: qcom: use spin_lock to guard qcom_regmap_list qcom_regmap_list can get corrupted if multiple clock controllers probe at same time. And clk_is_regmap can be invoked from clk_enable API. Hence add spin_lock to avoid list corruption. Change-Id: Iec5abdb2d6f1a47667e7f6d2430f6f32c0ca4829 Signed-off-by: Veera Vegivada --- drivers/clk/qcom/clk-regmap.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c index a6c2e4b4bce6..c1e76bbe0e54 100644 --- a/drivers/clk/qcom/clk-regmap.c +++ b/drivers/clk/qcom/clk-regmap.c @@ -13,7 +13,7 @@ #include "clk-debug.h" static LIST_HEAD(clk_regmap_list); -static DEFINE_MUTEX(clk_regmap_lock); +static DEFINE_SPINLOCK(clk_regmap_lock); /** * clk_is_enabled_regmap - standard is_enabled() for regmap users @@ -251,14 +251,14 @@ bool clk_is_regmap_clk(struct clk_hw *hw) bool is_regmap_clk = false; if (hw) { - mutex_lock(&clk_regmap_lock); + spin_lock(&clk_regmap_lock); list_for_each_entry(rclk, &clk_regmap_list, list_node) { if (&rclk->hw == hw) { is_regmap_clk = true; break; } } - mutex_unlock(&clk_regmap_lock); + spin_unlock(&clk_regmap_lock); } return is_regmap_clk; @@ -299,9 +299,9 @@ int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk) ret = devm_clk_hw_register(dev, &rclk->hw); if (!ret) { - mutex_lock(&clk_regmap_lock); + spin_lock(&clk_regmap_lock); list_add(&rclk->list_node, &clk_regmap_list); - mutex_unlock(&clk_regmap_lock); + spin_unlock(&clk_regmap_lock); ret = clk_hw_debug_register(dev, &rclk->hw); }