From aff2dc6b49fc642906eaa5523c5227c50fd77c50 Mon Sep 17 00:00:00 2001 From: Sudeep Holla Date: Fri, 10 Nov 2017 16:06:57 +0000 Subject: [PATCH 1/7] clk: versatile: add min/max rate boundaries for vexpress osc clock Clock framework has a provider API(clk_hw_set_rate_range) to set the min/max rate of a clock. Use the same to set the boundaries for the vexpress osc clock. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Signed-off-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/versatile/clk-vexpress-osc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index e7a868b83fe5..d3b5af2a02ab 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -104,6 +104,7 @@ static int vexpress_osc_probe(struct platform_device *pdev) return PTR_ERR(clk); of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, clk); + clk_hw_set_rate_range(&osc->hw, osc->rate_min, osc->rate_max); dev_dbg(&pdev->dev, "Registered clock '%s'\n", init.name); From a1d803d78b9e1ff82a0e5ef9d81202b23377f9e0 Mon Sep 17 00:00:00 2001 From: Brian Starkey Date: Mon, 13 Nov 2017 15:27:51 +0000 Subject: [PATCH 2/7] clk: versatile: Remove WARNs in ->round_rate() clk_round_rate() is intended to be used to round a given clock rate to the closest one achievable by the actual clock. This implies that the input to clk_round_rate() is expected to be unachievable - and such cases shouldn't be treated as exceptional. To reflect this, remove the WARN_ONs which trigger when an unachievable clock rate is passed to vexpress_osc_round_rate(). Reported-by: Vladimir Murzin Signed-off-by: Brian Starkey Acked-by: Sudeep Holla Signed-off-by: Stephen Boyd --- drivers/clk/versatile/clk-vexpress-osc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/versatile/clk-vexpress-osc.c b/drivers/clk/versatile/clk-vexpress-osc.c index d3b5af2a02ab..dd08ecb498be 100644 --- a/drivers/clk/versatile/clk-vexpress-osc.c +++ b/drivers/clk/versatile/clk-vexpress-osc.c @@ -44,10 +44,10 @@ static long vexpress_osc_round_rate(struct clk_hw *hw, unsigned long rate, { struct vexpress_osc *osc = to_vexpress_osc(hw); - if (WARN_ON(osc->rate_min && rate < osc->rate_min)) + if (osc->rate_min && rate < osc->rate_min) rate = osc->rate_min; - if (WARN_ON(osc->rate_max && rate > osc->rate_max)) + if (osc->rate_max && rate > osc->rate_max) rate = osc->rate_max; return rate; From 496037c015079ece7ebc1344fcab80f0618eae5e Mon Sep 17 00:00:00 2001 From: Srinivas Kandagatla Date: Thu, 7 Dec 2017 10:59:22 +0000 Subject: [PATCH 3/7] clk: qcom: gcc-msm8996: Mark aggre0 noc clks as critical aggre0 bus clks are not associated with any of the drivers, so its important that these clks are always on to get peripherals on this bus working. So mark them as critical. Eventually when we have a proper bus driver these clks can be marked appropriately. Without this patch pcie on db820c is not functional. Signed-off-by: Srinivas Kandagatla Signed-off-by: Stephen Boyd --- drivers/clk/qcom/gcc-msm8996.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/clk/qcom/gcc-msm8996.c b/drivers/clk/qcom/gcc-msm8996.c index 5d7451209206..3d6452932797 100644 --- a/drivers/clk/qcom/gcc-msm8996.c +++ b/drivers/clk/qcom/gcc-msm8996.c @@ -2895,7 +2895,7 @@ static struct clk_branch gcc_aggre0_snoc_axi_clk = { .name = "gcc_aggre0_snoc_axi_clk", .parent_names = (const char *[]){ "system_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2910,7 +2910,7 @@ static struct clk_branch gcc_aggre0_cnoc_ahb_clk = { .name = "gcc_aggre0_cnoc_ahb_clk", .parent_names = (const char *[]){ "config_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2925,7 +2925,7 @@ static struct clk_branch gcc_smmu_aggre0_axi_clk = { .name = "gcc_smmu_aggre0_axi_clk", .parent_names = (const char *[]){ "system_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, @@ -2940,7 +2940,7 @@ static struct clk_branch gcc_smmu_aggre0_ahb_clk = { .name = "gcc_smmu_aggre0_ahb_clk", .parent_names = (const char *[]){ "config_noc_clk_src" }, .num_parents = 1, - .flags = CLK_SET_RATE_PARENT, + .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, .ops = &clk_branch2_ops, }, }, From 5bc5673c098b03e8de29b9f87187bed7643bd5c6 Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Fri, 19 Jan 2018 21:37:15 +0800 Subject: [PATCH 4/7] Documentation: clk: enable lock is not held for clk_is_enabled API The core does not need to hold enable lock for clk_is_enabled API. Update the doc to reflect it. Cc: Jonathan Corbet Cc: Stephen Boyd Suggested-by: Stephen Boyd Signed-off-by: Dong Aisheng [sboyd: Clarified the last sentence a little more and fixed a spelling error] Signed-off-by: Stephen Boyd --- Documentation/clk.txt | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/Documentation/clk.txt b/Documentation/clk.txt index be909ed45970..511628bb3d3a 100644 --- a/Documentation/clk.txt +++ b/Documentation/clk.txt @@ -268,9 +268,19 @@ The common clock framework uses two global locks, the prepare lock and the enable lock. The enable lock is a spinlock and is held across calls to the .enable, -.disable and .is_enabled operations. Those operations are thus not allowed to -sleep, and calls to the clk_enable(), clk_disable() and clk_is_enabled() API -functions are allowed in atomic context. +.disable operations. Those operations are thus not allowed to sleep, +and calls to the clk_enable(), clk_disable() API functions are allowed in +atomic context. + +For clk_is_enabled() API, it is also designed to be allowed to be used in +atomic context. However, it doesn't really make any sense to hold the enable +lock in core, unless you want to do something else with the information of +the enable state with that lock held. Otherwise, seeing if a clk is enabled is +a one-shot read of the enabled state, which could just as easily change after +the function returns because the lock is released. Thus the user of this API +needs to handle synchronizing the read of the state with whatever they're +using it for to make sure that the enable state doesn't change during that +time. The prepare lock is a mutex and is held across calls to all other operations. All those operations are allowed to sleep, and calls to the corresponding API From 6e0d4ff4580c1272f4e4860bf22841ef31fd31ba Mon Sep 17 00:00:00 2001 From: Dong Aisheng Date: Tue, 23 Jan 2018 20:24:45 +0800 Subject: [PATCH 5/7] clk: add more __must_check for bulk APIs we need it even when !CONFIG_HAVE_CLK because it allows us to catch missing checking return values in the non-clk compile configurations too. More test coverage. Cc: Stephen Boyd Suggested-by: Stephen Boyd Signed-off-by: Dong Aisheng Signed-off-by: Stephen Boyd --- include/linux/clk.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/include/linux/clk.h b/include/linux/clk.h index 4c4ef9f34db3..0dbd0885b2c2 100644 --- a/include/linux/clk.h +++ b/include/linux/clk.h @@ -209,7 +209,7 @@ static inline int clk_prepare(struct clk *clk) return 0; } -static inline int clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks) +static inline int __must_check clk_bulk_prepare(int num_clks, struct clk_bulk_data *clks) { might_sleep(); return 0; @@ -603,8 +603,8 @@ static inline struct clk *clk_get(struct device *dev, const char *id) return NULL; } -static inline int clk_bulk_get(struct device *dev, int num_clks, - struct clk_bulk_data *clks) +static inline int __must_check clk_bulk_get(struct device *dev, int num_clks, + struct clk_bulk_data *clks) { return 0; } @@ -614,8 +614,8 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id) return NULL; } -static inline int devm_clk_bulk_get(struct device *dev, int num_clks, - struct clk_bulk_data *clks) +static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, + struct clk_bulk_data *clks) { return 0; } @@ -645,7 +645,7 @@ static inline int clk_enable(struct clk *clk) return 0; } -static inline int clk_bulk_enable(int num_clks, struct clk_bulk_data *clks) +static inline int __must_check clk_bulk_enable(int num_clks, struct clk_bulk_data *clks) { return 0; } @@ -719,8 +719,8 @@ static inline void clk_disable_unprepare(struct clk *clk) clk_unprepare(clk); } -static inline int clk_bulk_prepare_enable(int num_clks, - struct clk_bulk_data *clks) +static inline int __must_check clk_bulk_prepare_enable(int num_clks, + struct clk_bulk_data *clks) { int ret; From 91927ff6446c281a3aa5cf8875cf7f0853a2bb55 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 1 Feb 2018 16:33:26 -0800 Subject: [PATCH 6/7] clk: qcom: smd-rpm: Migrate to devm_of_clk_add_hw_provider() Signed-off-by: Stephen Boyd Signed-off-by: Stephen Boyd --- drivers/clk/qcom/clk-smd-rpm.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/drivers/clk/qcom/clk-smd-rpm.c b/drivers/clk/qcom/clk-smd-rpm.c index c26d9007bfc4..850c02a52248 100644 --- a/drivers/clk/qcom/clk-smd-rpm.c +++ b/drivers/clk/qcom/clk-smd-rpm.c @@ -686,7 +686,7 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) goto err; } - ret = of_clk_add_hw_provider(pdev->dev.of_node, qcom_smdrpm_clk_hw_get, + ret = devm_of_clk_add_hw_provider(&pdev->dev, qcom_smdrpm_clk_hw_get, rcc); if (ret) goto err; @@ -697,19 +697,12 @@ static int rpm_smd_clk_probe(struct platform_device *pdev) return ret; } -static int rpm_smd_clk_remove(struct platform_device *pdev) -{ - of_clk_del_provider(pdev->dev.of_node); - return 0; -} - static struct platform_driver rpm_smd_clk_driver = { .driver = { .name = "qcom-clk-smd-rpm", .of_match_table = rpm_smd_clk_match_table, }, .probe = rpm_smd_clk_probe, - .remove = rpm_smd_clk_remove, }; static int __init rpm_smd_clk_init(void) From fec0ef3f52735e1e9ac60f8644d4015ae21c0928 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 14 Feb 2018 17:48:00 +0200 Subject: [PATCH 7/7] clk: Re-use DEFINE_SHOW_ATTRIBUTE() macro ...instead of open coding file operations followed by custom ->open() callbacks per each attribute. Signed-off-by: Andy Shevchenko Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 60 ++++++----------------------------------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 0f686a9dac3e..cc97b18ac31f 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2486,19 +2486,7 @@ static int clk_summary_show(struct seq_file *s, void *data) return 0; } - - -static int clk_summary_open(struct inode *inode, struct file *file) -{ - return single_open(file, clk_summary_show, inode->i_private); -} - -static const struct file_operations clk_summary_fops = { - .open = clk_summary_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(clk_summary); static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level) { @@ -2532,7 +2520,7 @@ static void clk_dump_subtree(struct seq_file *s, struct clk_core *c, int level) seq_putc(s, '}'); } -static int clk_dump(struct seq_file *s, void *data) +static int clk_dump_show(struct seq_file *s, void *data) { struct clk_core *c; bool first_node = true; @@ -2555,19 +2543,7 @@ static int clk_dump(struct seq_file *s, void *data) seq_puts(s, "}\n"); return 0; } - - -static int clk_dump_open(struct inode *inode, struct file *file) -{ - return single_open(file, clk_dump, inode->i_private); -} - -static const struct file_operations clk_dump_fops = { - .open = clk_dump_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(clk_dump); static const struct { unsigned long flag; @@ -2589,7 +2565,7 @@ static const struct { #undef ENTRY }; -static int clk_flags_dump(struct seq_file *s, void *data) +static int clk_flags_show(struct seq_file *s, void *data) { struct clk_core *core = s->private; unsigned long flags = core->flags; @@ -2608,20 +2584,9 @@ static int clk_flags_dump(struct seq_file *s, void *data) return 0; } +DEFINE_SHOW_ATTRIBUTE(clk_flags); -static int clk_flags_open(struct inode *inode, struct file *file) -{ - return single_open(file, clk_flags_dump, inode->i_private); -} - -static const struct file_operations clk_flags_fops = { - .open = clk_flags_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int possible_parents_dump(struct seq_file *s, void *data) +static int possible_parents_show(struct seq_file *s, void *data) { struct clk_core *core = s->private; int i; @@ -2633,18 +2598,7 @@ static int possible_parents_dump(struct seq_file *s, void *data) return 0; } - -static int possible_parents_open(struct inode *inode, struct file *file) -{ - return single_open(file, possible_parents_dump, inode->i_private); -} - -static const struct file_operations possible_parents_fops = { - .open = possible_parents_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; +DEFINE_SHOW_ATTRIBUTE(possible_parents); static int clk_debug_create_one(struct clk_core *core, struct dentry *pdentry) {