From 28a0b0984e76df8fd64b6850fa56cf5201e6e638 Mon Sep 17 00:00:00 2001 From: Liang He Date: Fri, 17 Jun 2022 09:43:08 +0800 Subject: clk: nomadik: Add missing of_node_put() In nomadik_src_init(), of_find_matching_node() will return a node pointer with refcount incremented. We should use of_node_put() in fail path or when it is not used anymore. Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220617014308.4001511-1-windhl@126.com Reviewed-by: Linus Walleij Signed-off-by: Stephen Boyd --- drivers/clk/clk-nomadik.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-nomadik.c b/drivers/clk/clk-nomadik.c index bad2677e11ae..71fbe687fa7b 100644 --- a/drivers/clk/clk-nomadik.c +++ b/drivers/clk/clk-nomadik.c @@ -99,7 +99,7 @@ static void __init nomadik_src_init(void) if (!src_base) { pr_err("%s: must have src parent node with REGS (%pOFn)\n", __func__, np); - return; + goto out_put; } /* Set all timers to use the 2.4 MHz TIMCLK */ @@ -132,6 +132,9 @@ static void __init nomadik_src_init(void) } writel(val, src_base + SRC_XTALCR); register_reboot_notifier(&nomadik_clk_reboot_notifier); + +out_put: + of_node_put(np); } /** -- cgit v1.2.3 From 89ab396d712f7c91fe94f55cff23460426f5fc81 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 28 Jun 2022 22:10:38 +0800 Subject: clk: meson: Hold reference returned by of_get_parent() We should hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Fixes: 88e2da81241e ("clk: meson: aoclk: refactor common code into dedicated file") Fixes: 6682bd4d443f ("clk: meson: factorise meson64 peripheral clock controller drivers") Fixes: bb6eddd1d28c ("clk: meson: meson8b: use the HHI syscon if available") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220628141038.168383-1-windhl@126.com Reviewed-by: Neil Armstrong Reviewed-by: Martin Blumenstingl Signed-off-by: Stephen Boyd --- drivers/clk/meson/meson-aoclk.c | 5 ++++- drivers/clk/meson/meson-eeclk.c | 5 ++++- drivers/clk/meson/meson8b.c | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c index 27cd2c1f3f61..434cd8f9de82 100644 --- a/drivers/clk/meson/meson-aoclk.c +++ b/drivers/clk/meson/meson-aoclk.c @@ -38,6 +38,7 @@ int meson_aoclkc_probe(struct platform_device *pdev) struct meson_aoclk_reset_controller *rstc; struct meson_aoclk_data *data; struct device *dev = &pdev->dev; + struct device_node *np; struct regmap *regmap; int ret, clkid; @@ -49,7 +50,9 @@ int meson_aoclkc_probe(struct platform_device *pdev) if (!rstc) return -ENOMEM; - regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); + np = of_get_parent(dev->of_node); + regmap = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(regmap)) { dev_err(dev, "failed to get regmap\n"); return PTR_ERR(regmap); diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c index 8d5a5dab955a..0e5e6b57eb20 100644 --- a/drivers/clk/meson/meson-eeclk.c +++ b/drivers/clk/meson/meson-eeclk.c @@ -18,6 +18,7 @@ int meson_eeclkc_probe(struct platform_device *pdev) { const struct meson_eeclkc_data *data; struct device *dev = &pdev->dev; + struct device_node *np; struct regmap *map; int ret, i; @@ -26,7 +27,9 @@ int meson_eeclkc_probe(struct platform_device *pdev) return -EINVAL; /* Get the hhi system controller node */ - map = syscon_node_to_regmap(of_get_parent(dev->of_node)); + np = of_get_parent(dev->of_node); + map = syscon_node_to_regmap(np); + of_node_put(np); if (IS_ERR(map)) { dev_err(dev, "failed to get HHI regmap\n"); diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c index 8f3b7a94a667..827e78fb16a8 100644 --- a/drivers/clk/meson/meson8b.c +++ b/drivers/clk/meson/meson8b.c @@ -3792,12 +3792,15 @@ static void __init meson8b_clkc_init_common(struct device_node *np, struct clk_hw_onecell_data *clk_hw_onecell_data) { struct meson8b_clk_reset *rstc; + struct device_node *parent_np; const char *notifier_clk_name; struct clk *notifier_clk; struct regmap *map; int i, ret; - map = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + map = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(map)) { pr_err("failed to get HHI regmap - Trying obsolete regs\n"); return; -- cgit v1.2.3 From 02bd544f98ae96e2f8fde759696f725f0966cce6 Mon Sep 17 00:00:00 2001 From: Liang He Date: Fri, 17 Jun 2022 09:59:18 +0800 Subject: clk: tegra: Add missing of_node_put() In tegra124_132_clock_init_pre() and tegra30_clock_init(), of_find_matching_node() will return a node pointer with refcount incremented. We should use of_node_put() when it is not used anymore. Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220617015918.4001865-1-windhl@126.com Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra124.c | 1 + drivers/clk/tegra/clk-tegra30.c | 1 + 2 files changed, 2 insertions(+) diff --git a/drivers/clk/tegra/clk-tegra124.c b/drivers/clk/tegra/clk-tegra124.c index 934520aab6e3..a9d4efcef2d4 100644 --- a/drivers/clk/tegra/clk-tegra124.c +++ b/drivers/clk/tegra/clk-tegra124.c @@ -1471,6 +1471,7 @@ static void __init tegra124_132_clock_init_pre(struct device_node *np) } pmc_base = of_iomap(node, 0); + of_node_put(node); if (!pmc_base) { pr_err("Can't map pmc registers\n"); WARN_ON(1); diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 04b496123820..168c07d5a5f2 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c @@ -1320,6 +1320,7 @@ static void __init tegra30_clock_init(struct device_node *np) } pmc_base = of_iomap(node, 0); + of_node_put(node); if (!pmc_base) { pr_err("Can't map pmc registers\n"); BUG(); -- cgit v1.2.3 From 429973306f860470cbbb8402c8c53143b450faba Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 28 Jun 2022 22:24:15 +0800 Subject: clk: st: Hold reference returned by of_get_parent() We should hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Fixes: 3efe64ef5186 ("clk: st: clkgen-fsyn: search reg within node or parent") Fixes: 810251b0d36a ("clk: st: clkgen-mux: search reg within node or parent") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220628142416.169808-1-windhl@126.com Signed-off-by: Stephen Boyd --- drivers/clk/st/clkgen-fsyn.c | 5 ++++- drivers/clk/st/clkgen-mux.c | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clk/st/clkgen-fsyn.c b/drivers/clk/st/clkgen-fsyn.c index 582a22c04919..d820292a381d 100644 --- a/drivers/clk/st/clkgen-fsyn.c +++ b/drivers/clk/st/clkgen-fsyn.c @@ -987,6 +987,7 @@ static void __init st_of_quadfs_setup(struct device_node *np, const char *pll_name, *clk_parent_name; void __iomem *reg; spinlock_t *lock; + struct device_node *parent_np; /* * First check for reg property within the node to keep backward @@ -994,7 +995,9 @@ static void __init st_of_quadfs_setup(struct device_node *np, */ reg = of_iomap(np, 0); if (!reg) { - reg = of_iomap(of_get_parent(np), 0); + parent_np = of_get_parent(np); + reg = of_iomap(parent_np, 0); + of_node_put(parent_np); if (!reg) { pr_err("%s: Failed to get base address\n", __func__); return; diff --git a/drivers/clk/st/clkgen-mux.c b/drivers/clk/st/clkgen-mux.c index ee39af7a0b72..596e939ad905 100644 --- a/drivers/clk/st/clkgen-mux.c +++ b/drivers/clk/st/clkgen-mux.c @@ -56,6 +56,7 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np, void __iomem *reg; const char **parents; int num_parents = 0; + struct device_node *parent_np; /* * First check for reg property within the node to keep backward @@ -63,7 +64,9 @@ static void __init st_of_clkgen_mux_setup(struct device_node *np, */ reg = of_iomap(np, 0); if (!reg) { - reg = of_iomap(of_get_parent(np), 0); + parent_np = of_get_parent(np); + reg = of_iomap(parent_np, 0); + of_node_put(parent_np); if (!reg) { pr_err("%s: Failed to get base address\n", __func__); return; -- cgit v1.2.3 From 1d6aa08c54cd0e005210ab8e3b1e92ede70f8a4f Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 28 Jun 2022 22:31:55 +0800 Subject: clk: oxnas: Hold reference returned by of_get_parent() In oxnas_stdclk_probe(), we need to hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Fixes: 0bbd72b4c64f ("clk: Add Oxford Semiconductor OXNAS Standard Clocks") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220628143155.170550-1-windhl@126.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-oxnas.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-oxnas.c b/drivers/clk/clk-oxnas.c index cda5e258355b..584e293156ad 100644 --- a/drivers/clk/clk-oxnas.c +++ b/drivers/clk/clk-oxnas.c @@ -207,7 +207,7 @@ static const struct of_device_id oxnas_stdclk_dt_ids[] = { static int oxnas_stdclk_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device_node *np = pdev->dev.of_node, *parent_np; const struct oxnas_stdclk_data *data; struct regmap *regmap; int ret; @@ -215,7 +215,9 @@ static int oxnas_stdclk_probe(struct platform_device *pdev) data = of_device_get_match_data(&pdev->dev); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) { dev_err(&pdev->dev, "failed to have parent regmap\n"); return PTR_ERR(regmap); -- cgit v1.2.3 From a8ea4273bc26256ce3cce83164f0f51c5bf6e127 Mon Sep 17 00:00:00 2001 From: Liang He Date: Tue, 28 Jun 2022 22:38:51 +0800 Subject: clk: qoriq: Hold reference returned by of_get_parent() In legacy_init_clockgen(), we need to hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Beside, in create_sysclk(), we need to call of_node_put() on 'sysclk' also for refcount balance. Fixes: 0dfc86b3173f ("clk: qoriq: Move chip-specific knowledge into driver") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220628143851.171299-1-windhl@126.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-qoriq.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-qoriq.c b/drivers/clk/clk-qoriq.c index 88898b97a443..5eddb9f0d6bd 100644 --- a/drivers/clk/clk-qoriq.c +++ b/drivers/clk/clk-qoriq.c @@ -1063,8 +1063,13 @@ static void __init _clockgen_init(struct device_node *np, bool legacy); */ static void __init legacy_init_clockgen(struct device_node *np) { - if (!clockgen.node) - _clockgen_init(of_get_parent(np), true); + if (!clockgen.node) { + struct device_node *parent_np; + + parent_np = of_get_parent(np); + _clockgen_init(parent_np, true); + of_node_put(parent_np); + } } /* Legacy node */ @@ -1159,6 +1164,7 @@ static struct clk * __init create_sysclk(const char *name) sysclk = of_get_child_by_name(clockgen.node, "sysclk"); if (sysclk) { clk = sysclk_from_fixed(sysclk, name); + of_node_put(sysclk); if (!IS_ERR(clk)) return clk; } -- cgit v1.2.3 From b3ff02c5df4712b565b290c6f268a79a72a28e74 Mon Sep 17 00:00:00 2001 From: Liang He Date: Thu, 30 Jun 2022 22:39:49 +0800 Subject: clk: at91: dt-compat: Hold reference returned by of_get_parent() We need to hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220630143949.218922-1-windhl@126.com Reviewed-by: Claudiu Beznea Signed-off-by: Stephen Boyd --- drivers/clk/at91/dt-compat.c | 108 +++++++++++++++++++++++++++++++++---------- 1 file changed, 84 insertions(+), 24 deletions(-) diff --git a/drivers/clk/at91/dt-compat.c b/drivers/clk/at91/dt-compat.c index 8ca8bcacf66d..85a964cb2d89 100644 --- a/drivers/clk/at91/dt-compat.c +++ b/drivers/clk/at91/dt-compat.c @@ -33,8 +33,11 @@ static void __init of_sama5d2_clk_audio_pll_frac_setup(struct device_node *np) const char *name = np->name; const char *parent_name; struct regmap *regmap; + struct device_node *parent_np; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -56,8 +59,11 @@ static void __init of_sama5d2_clk_audio_pll_pad_setup(struct device_node *np) const char *name = np->name; const char *parent_name; struct regmap *regmap; + struct device_node *parent_np; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -79,8 +85,11 @@ static void __init of_sama5d2_clk_audio_pll_pmc_setup(struct device_node *np) const char *name = np->name; const char *parent_name; struct regmap *regmap; + struct device_node *parent_np; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -120,7 +129,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) struct clk_hw *hw; unsigned int num_parents; const char *parent_names[GENERATED_SOURCE_MAX]; - struct device_node *gcknp; + struct device_node *gcknp, *parent_np; struct clk_range range = CLK_RANGE(0, 0); struct regmap *regmap; @@ -134,7 +143,9 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) if (!num || num > PERIPHERAL_MAX) return; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -180,8 +191,11 @@ static void __init of_sama5d4_clk_h32mx_setup(struct device_node *np) const char *name = np->name; const char *parent_name; struct regmap *regmap; + struct device_node *parent_np; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -243,12 +257,15 @@ static void __init of_at91rm9200_clk_main_osc_setup(struct device_node *np) const char *parent_name; struct regmap *regmap; bool bypass; + struct device_node *parent_np; of_property_read_string(np, "clock-output-names", &name); bypass = of_property_read_bool(np, "atmel,osc-bypass"); parent_name = of_clk_get_parent_name(np, 0); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -268,12 +285,15 @@ static void __init of_at91sam9x5_clk_main_rc_osc_setup(struct device_node *np) u32 accuracy = 0; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; of_property_read_string(np, "clock-output-names", &name); of_property_read_u32(np, "clock-frequency", &frequency); of_property_read_u32(np, "clock-accuracy", &accuracy); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -292,11 +312,14 @@ static void __init of_at91rm9200_clk_main_setup(struct device_node *np) const char *parent_name; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -316,13 +339,16 @@ static void __init of_at91sam9x5_clk_main_setup(struct device_node *np) unsigned int num_parents; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; num_parents = of_clk_get_parent_count(np); if (num_parents == 0 || num_parents > 2) return; of_clk_parent_fill(np, parent_names, num_parents); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -373,6 +399,7 @@ of_at91_clk_master_setup(struct device_node *np, const char *name = np->name; struct clk_master_characteristics *characteristics; struct regmap *regmap; + struct device_node *parent_np; num_parents = of_clk_get_parent_count(np); if (num_parents == 0 || num_parents > MASTER_SOURCE_MAX) @@ -386,7 +413,9 @@ of_at91_clk_master_setup(struct device_node *np, if (!characteristics) return; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -433,6 +462,7 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) const char *name; struct device_node *periphclknp; struct regmap *regmap; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); if (!parent_name) @@ -442,7 +472,9 @@ of_at91_clk_periph_setup(struct device_node *np, u8 type) if (!num || num > PERIPHERAL_MAX) return; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -601,6 +633,7 @@ of_at91_clk_pll_setup(struct device_node *np, struct regmap *regmap; const char *parent_name; const char *name = np->name; + struct device_node *parent_np; struct clk_pll_characteristics *characteristics; if (of_property_read_u32(np, "reg", &id)) @@ -610,7 +643,9 @@ of_at91_clk_pll_setup(struct device_node *np, of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -665,12 +700,15 @@ of_at91sam9x5_clk_plldiv_setup(struct device_node *np) const char *parent_name; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -694,7 +732,7 @@ of_at91_clk_prog_setup(struct device_node *np, unsigned int num_parents; const char *parent_names[PROG_SOURCE_MAX]; const char *name; - struct device_node *progclknp; + struct device_node *progclknp, *parent_np; struct regmap *regmap; num_parents = of_clk_get_parent_count(np); @@ -707,7 +745,9 @@ of_at91_clk_prog_setup(struct device_node *np, if (!num || num > (PROG_ID_MAX + 1)) return; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -756,13 +796,16 @@ static void __init of_at91sam9260_clk_slow_setup(struct device_node *np) unsigned int num_parents; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; num_parents = of_clk_get_parent_count(np); if (num_parents != 2) return; of_clk_parent_fill(np, parent_names, num_parents); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -788,6 +831,7 @@ static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np) const char *parent_names[SMD_SOURCE_MAX]; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; num_parents = of_clk_get_parent_count(np); if (num_parents == 0 || num_parents > SMD_SOURCE_MAX) @@ -797,7 +841,9 @@ static void __init of_at91sam9x5_clk_smd_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -818,7 +864,7 @@ static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) u32 id; struct clk_hw *hw; const char *name; - struct device_node *sysclknp; + struct device_node *sysclknp, *parent_np; const char *parent_name; struct regmap *regmap; @@ -826,7 +872,9 @@ static void __init of_at91rm9200_clk_sys_setup(struct device_node *np) if (num > (SYSTEM_MAX_ID + 1)) return; - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -859,6 +907,7 @@ static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np) const char *parent_names[USB_SOURCE_MAX]; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; num_parents = of_clk_get_parent_count(np); if (num_parents == 0 || num_parents > USB_SOURCE_MAX) @@ -868,7 +917,9 @@ static void __init of_at91sam9x5_clk_usb_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -888,6 +939,7 @@ static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np) const char *parent_name; const char *name = np->name; struct regmap *regmap; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); if (!parent_name) @@ -895,7 +947,9 @@ static void __init of_at91sam9n12_clk_usb_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; @@ -915,6 +969,7 @@ static void __init of_at91rm9200_clk_usb_setup(struct device_node *np) const char *name = np->name; u32 divisors[4] = {0, 0, 0, 0}; struct regmap *regmap; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); if (!parent_name) @@ -926,7 +981,9 @@ static void __init of_at91rm9200_clk_usb_setup(struct device_node *np) of_property_read_string(np, "clock-output-names", &name); - regmap = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap)) return; hw = at91rm9200_clk_register_usb(regmap, name, parent_name, divisors); @@ -946,12 +1003,15 @@ static void __init of_at91sam9x5_clk_utmi_setup(struct device_node *np) const char *parent_name; const char *name = np->name; struct regmap *regmap_pmc, *regmap_sfr; + struct device_node *parent_np; parent_name = of_clk_get_parent_name(np, 0); of_property_read_string(np, "clock-output-names", &name); - regmap_pmc = syscon_node_to_regmap(of_get_parent(np)); + parent_np = of_get_parent(np); + regmap_pmc = syscon_node_to_regmap(parent_np); + of_node_put(parent_np); if (IS_ERR(regmap_pmc)) return; -- cgit v1.2.3 From 37c381b812dcbfde9c3f1f3d3e75fdfc1b40d5bc Mon Sep 17 00:00:00 2001 From: Liang He Date: Fri, 8 Jul 2022 16:49:00 +0800 Subject: clk: berlin: Add of_node_put() for of_get_parent() In berlin2_clock_setup() and berlin2q_clock_setup(), we need to call of_node_put() for the reference returned by of_get_parent() which has increased the refcount. We should call *_put() in fail path or when it is not used anymore. Fixes: 26b3b6b959b2 ("clk: berlin: prepare simple-mfd conversion") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220708084900.311684-1-windhl@126.com Signed-off-by: Stephen Boyd --- drivers/clk/berlin/bg2.c | 5 ++++- drivers/clk/berlin/bg2q.c | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/clk/berlin/bg2.c b/drivers/clk/berlin/bg2.c index bccdfa00fd37..67a9edbba29c 100644 --- a/drivers/clk/berlin/bg2.c +++ b/drivers/clk/berlin/bg2.c @@ -500,12 +500,15 @@ static void __init berlin2_clock_setup(struct device_node *np) int n, ret; clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); - if (!clk_data) + if (!clk_data) { + of_node_put(parent_np); return; + } clk_data->num = MAX_CLKS; hws = clk_data->hws; gbase = of_iomap(parent_np, 0); + of_node_put(parent_np); if (!gbase) return; diff --git a/drivers/clk/berlin/bg2q.c b/drivers/clk/berlin/bg2q.c index e9518d35f262..dd2784bb75b6 100644 --- a/drivers/clk/berlin/bg2q.c +++ b/drivers/clk/berlin/bg2q.c @@ -286,19 +286,23 @@ static void __init berlin2q_clock_setup(struct device_node *np) int n, ret; clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); - if (!clk_data) + if (!clk_data) { + of_node_put(parent_np); return; + } clk_data->num = MAX_CLKS; hws = clk_data->hws; gbase = of_iomap(parent_np, 0); if (!gbase) { + of_node_put(parent_np); pr_err("%pOF: Unable to map global base\n", np); return; } /* BG2Q CPU PLL is not part of global registers */ cpupll_base = of_iomap(parent_np, 1); + of_node_put(parent_np); if (!cpupll_base) { pr_err("%pOF: Unable to map cpupll base\n", np); iounmap(gbase); -- cgit v1.2.3 From 91e6455bf715fb1558a0bf8f645ec1c131254a3c Mon Sep 17 00:00:00 2001 From: Liang He Date: Mon, 4 Jul 2022 08:47:29 +0800 Subject: clk: sprd: Hold reference returned by of_get_parent() We should hold the reference returned by of_get_parent() and use it to call of_node_put() for refcount balance. Fixes: f95e8c7923d1 ("clk: sprd: support to get regmap from parent node") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220704004729.272481-1-windhl@126.com Reviewed-by: Orson Zhai Signed-off-by: Stephen Boyd --- drivers/clk/sprd/common.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c index d620bbbcdfc8..ce81e4087a8f 100644 --- a/drivers/clk/sprd/common.c +++ b/drivers/clk/sprd/common.c @@ -41,7 +41,7 @@ int sprd_clk_regmap_init(struct platform_device *pdev, { void __iomem *base; struct device *dev = &pdev->dev; - struct device_node *node = dev->of_node; + struct device_node *node = dev->of_node, *np; struct regmap *regmap; if (of_find_property(node, "sprd,syscon", NULL)) { @@ -50,9 +50,10 @@ int sprd_clk_regmap_init(struct platform_device *pdev, pr_err("%s: failed to get syscon regmap\n", __func__); return PTR_ERR(regmap); } - } else if (of_device_is_compatible(of_get_parent(dev->of_node), - "syscon")) { - regmap = device_node_to_regmap(of_get_parent(dev->of_node)); + } else if (of_device_is_compatible(np = of_get_parent(node), "syscon") || + (of_node_put(np), 0)) { + regmap = device_node_to_regmap(np); + of_node_put(np); if (IS_ERR(regmap)) { dev_err(dev, "failed to get regmap from its parent.\n"); return PTR_ERR(regmap); -- cgit v1.2.3 From 0384759b3dbc5e489299b55a436dde8462c1a623 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 13 Jun 2022 10:16:31 +0200 Subject: dt-bindings: clock: Move lochnagar.h to dt-bindings/clock Most of the clock-related dt-binding header files are located in include/dt-bindings/clock. It would be good to keep all the similar header files at a single location. This was discovered while investigating the state of ownership of the files in include/dt-bindings/ according to the MAINTAINERS file. This change here is similar to commit 8e28918a85a0 ("dt-bindings: clock: Move ti-dra7-atl.h to dt-bindings/clock") and commit 35d35aae8177 ("dt-bindings: clock: Move at91.h to dt-bindigs/clock"). Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20220613081632.2159-2-lukas.bulwahn@gmail.com Acked-by: Charles Keepax Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/mfd/cirrus,lochnagar.yaml | 2 +- MAINTAINERS | 2 +- drivers/clk/clk-lochnagar.c | 2 +- include/dt-bindings/clk/lochnagar.h | 26 ---------------------- include/dt-bindings/clock/lochnagar.h | 26 ++++++++++++++++++++++ 5 files changed, 29 insertions(+), 29 deletions(-) delete mode 100644 include/dt-bindings/clk/lochnagar.h create mode 100644 include/dt-bindings/clock/lochnagar.h diff --git a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml index ad285cb480c9..ef4814ced8db 100644 --- a/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml +++ b/Documentation/devicetree/bindings/mfd/cirrus,lochnagar.yaml @@ -261,7 +261,7 @@ additionalProperties: false examples: - | - #include + #include #include i2c@e0004000 { #address-cells = <1>; diff --git a/MAINTAINERS b/MAINTAINERS index 8a5012ba6ff9..160a40efd620 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4957,7 +4957,7 @@ F: drivers/hwmon/lochnagar-hwmon.c F: drivers/mfd/lochnagar-i2c.c F: drivers/pinctrl/cirrus/pinctrl-lochnagar.c F: drivers/regulator/lochnagar-regulator.c -F: include/dt-bindings/clk/lochnagar.h +F: include/dt-bindings/clock/lochnagar.h F: include/dt-bindings/pinctrl/lochnagar.h F: include/linux/mfd/lochnagar* F: sound/soc/codecs/lochnagar-sc.c diff --git a/drivers/clk/clk-lochnagar.c b/drivers/clk/clk-lochnagar.c index 565bcd0cdde9..80944bf482e9 100644 --- a/drivers/clk/clk-lochnagar.c +++ b/drivers/clk/clk-lochnagar.c @@ -19,7 +19,7 @@ #include #include -#include +#include #define LOCHNAGAR_NUM_CLOCKS (LOCHNAGAR_SPDIF_CLKOUT + 1) diff --git a/include/dt-bindings/clk/lochnagar.h b/include/dt-bindings/clk/lochnagar.h deleted file mode 100644 index 8fa20551ff17..000000000000 --- a/include/dt-bindings/clk/lochnagar.h +++ /dev/null @@ -1,26 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Device Tree defines for Lochnagar clocking - * - * Copyright (c) 2017-2018 Cirrus Logic, Inc. and - * Cirrus Logic International Semiconductor Ltd. - * - * Author: Charles Keepax - */ - -#ifndef DT_BINDINGS_CLK_LOCHNAGAR_H -#define DT_BINDINGS_CLK_LOCHNAGAR_H - -#define LOCHNAGAR_CDC_MCLK1 0 -#define LOCHNAGAR_CDC_MCLK2 1 -#define LOCHNAGAR_DSP_CLKIN 2 -#define LOCHNAGAR_GF_CLKOUT1 3 -#define LOCHNAGAR_GF_CLKOUT2 4 -#define LOCHNAGAR_PSIA1_MCLK 5 -#define LOCHNAGAR_PSIA2_MCLK 6 -#define LOCHNAGAR_SPDIF_MCLK 7 -#define LOCHNAGAR_ADAT_MCLK 8 -#define LOCHNAGAR_SOUNDCARD_MCLK 9 -#define LOCHNAGAR_SPDIF_CLKOUT 10 - -#endif diff --git a/include/dt-bindings/clock/lochnagar.h b/include/dt-bindings/clock/lochnagar.h new file mode 100644 index 000000000000..8fa20551ff17 --- /dev/null +++ b/include/dt-bindings/clock/lochnagar.h @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Device Tree defines for Lochnagar clocking + * + * Copyright (c) 2017-2018 Cirrus Logic, Inc. and + * Cirrus Logic International Semiconductor Ltd. + * + * Author: Charles Keepax + */ + +#ifndef DT_BINDINGS_CLK_LOCHNAGAR_H +#define DT_BINDINGS_CLK_LOCHNAGAR_H + +#define LOCHNAGAR_CDC_MCLK1 0 +#define LOCHNAGAR_CDC_MCLK2 1 +#define LOCHNAGAR_DSP_CLKIN 2 +#define LOCHNAGAR_GF_CLKOUT1 3 +#define LOCHNAGAR_GF_CLKOUT2 4 +#define LOCHNAGAR_PSIA1_MCLK 5 +#define LOCHNAGAR_PSIA2_MCLK 6 +#define LOCHNAGAR_SPDIF_MCLK 7 +#define LOCHNAGAR_ADAT_MCLK 8 +#define LOCHNAGAR_SOUNDCARD_MCLK 9 +#define LOCHNAGAR_SPDIF_CLKOUT 10 + +#endif -- cgit v1.2.3 From ba6165bc8344e1b18ed49249916ca62ba49d38ad Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Mon, 13 Jun 2022 10:16:32 +0200 Subject: dt-bindings: clock: Move versaclock.h to dt-bindings/clock Most of the clock related dt-binding header files are located in dt-bindings/clock folder. It would be good to keep all the similar header files at a single location. This was discovered while investigating the state of ownership of the files in include/dt-bindings/ according to the MAINTAINERS file. This change here is similar to commit 8e28918a85a0 ("dt-bindings: clock: Move ti-dra7-atl.h to dt-bindings/clock") and commit 35d35aae8177 ("dt-bindings: clock: Move at91.h to dt-bindigs/clock"). Signed-off-by: Lukas Bulwahn Link: https://lore.kernel.org/r/20220613081632.2159-3-lukas.bulwahn@gmail.com Reviewed-by: Luca Ceresoli Reviewed-by: Luca Ceresoli Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/idt,versaclock5.yaml | 4 ++-- arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi | 2 +- arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi | 2 +- drivers/clk/clk-versaclock5.c | 2 +- include/dt-bindings/clk/versaclock.h | 13 ------------- include/dt-bindings/clock/versaclock.h | 13 +++++++++++++ 6 files changed, 18 insertions(+), 18 deletions(-) delete mode 100644 include/dt-bindings/clk/versaclock.h create mode 100644 include/dt-bindings/clock/versaclock.h diff --git a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml index 7c331bfbe370..c1b838524064 100644 --- a/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml +++ b/Documentation/devicetree/bindings/clock/idt,versaclock5.yaml @@ -108,7 +108,7 @@ patternProperties: properties: idt,mode: description: - The output drive mode. Values defined in dt-bindings/clk/versaclock.h + The output drive mode. Values defined in dt-bindings/clock/versaclock.h $ref: /schemas/types.yaml#/definitions/uint32 minimum: 0 maximum: 6 @@ -151,7 +151,7 @@ additionalProperties: false examples: - | - #include + #include /* 25MHz reference crystal */ ref25: ref25m { diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi index 63e7a39e100e..8166e3c1ff4e 100644 --- a/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi +++ b/arch/arm64/boot/dts/renesas/beacon-renesom-baseboard.dtsi @@ -5,7 +5,7 @@ #include #include -#include +#include / { backlight_lvds: backlight-lvds { diff --git a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi index f5c1d74b738b..d3fc8ffd5b4c 100644 --- a/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi +++ b/arch/arm64/boot/dts/renesas/beacon-renesom-som.dtsi @@ -4,7 +4,7 @@ */ #include -#include +#include / { memory@48000000 { diff --git a/drivers/clk/clk-versaclock5.c b/drivers/clk/clk-versaclock5.c index e7be3e54b9be..b8c556dbeba0 100644 --- a/drivers/clk/clk-versaclock5.c +++ b/drivers/clk/clk-versaclock5.c @@ -24,7 +24,7 @@ #include #include -#include +#include /* VersaClock5 registers */ #define VC5_OTP_CONTROL 0x00 diff --git a/include/dt-bindings/clk/versaclock.h b/include/dt-bindings/clk/versaclock.h deleted file mode 100644 index c6a6a0946564..000000000000 --- a/include/dt-bindings/clk/versaclock.h +++ /dev/null @@ -1,13 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ - -/* This file defines field values used by the versaclock 6 family - * for defining output type - */ - -#define VC5_LVPECL 0 -#define VC5_CMOS 1 -#define VC5_HCSL33 2 -#define VC5_LVDS 3 -#define VC5_CMOS2 4 -#define VC5_CMOSD 5 -#define VC5_HCSL25 6 diff --git a/include/dt-bindings/clock/versaclock.h b/include/dt-bindings/clock/versaclock.h new file mode 100644 index 000000000000..c6a6a0946564 --- /dev/null +++ b/include/dt-bindings/clock/versaclock.h @@ -0,0 +1,13 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +/* This file defines field values used by the versaclock 6 family + * for defining output type + */ + +#define VC5_LVPECL 0 +#define VC5_CMOS 1 +#define VC5_HCSL33 2 +#define VC5_LVDS 3 +#define VC5_CMOS2 4 +#define VC5_CMOSD 5 +#define VC5_HCSL25 6 -- cgit v1.2.3 From 450c787cec18fffb405e623a662d4095ade81942 Mon Sep 17 00:00:00 2001 From: Conor Dooley Date: Wed, 27 Jul 2022 14:10:16 +0100 Subject: dt-bindings: clock: gpio-gate-clock: Convert to json-schema Convert the simple GPIO clock gate Device Tree binding to json-schema and fix-up references to this file in other text format bindings. Jyri Sarha is the file's only editor/author so they have been added as maintainer of the new yaml binding. Signed-off-by: Conor Dooley Link: https://lore.kernel.org/r/20220727131015.2073100-1-conor.dooley@microchip.com Reviewed-by: Krzysztof Kozlowski Signed-off-by: Stephen Boyd --- .../devicetree/bindings/clock/gpio-gate-clock.txt | 21 ----------- .../devicetree/bindings/clock/gpio-gate-clock.yaml | 42 ++++++++++++++++++++++ .../devicetree/bindings/clock/ti/gate.txt | 2 +- .../devicetree/bindings/clock/ti/interface.txt | 2 +- 4 files changed, 44 insertions(+), 23 deletions(-) delete mode 100644 Documentation/devicetree/bindings/clock/gpio-gate-clock.txt create mode 100644 Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml diff --git a/Documentation/devicetree/bindings/clock/gpio-gate-clock.txt b/Documentation/devicetree/bindings/clock/gpio-gate-clock.txt deleted file mode 100644 index d3379ff9b84b..000000000000 --- a/Documentation/devicetree/bindings/clock/gpio-gate-clock.txt +++ /dev/null @@ -1,21 +0,0 @@ -Binding for simple gpio gated clock. - -This binding uses the common clock binding[1]. - -[1] Documentation/devicetree/bindings/clock/clock-bindings.txt - -Required properties: -- compatible : shall be "gpio-gate-clock". -- #clock-cells : from common clock binding; shall be set to 0. -- enable-gpios : GPIO reference for enabling and disabling the clock. - -Optional properties: -- clocks: Maximum of one parent clock is supported. - -Example: - clock { - compatible = "gpio-gate-clock"; - clocks = <&parentclk>; - #clock-cells = <0>; - enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; - }; diff --git a/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml new file mode 100644 index 000000000000..d09d0e3f0c6e --- /dev/null +++ b/Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml @@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/gpio-gate-clock.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Simple GPIO clock gate + +maintainers: + - Jyri Sarha + +properties: + compatible: + const: gpio-gate-clock + + clocks: + maxItems: 1 + + '#clock-cells': + const: 0 + + enable-gpios: + description: GPIO reference for enabling and disabling the clock. + maxItems: 1 + +required: + - compatible + - '#clock-cells' + - enable-gpios + +additionalProperties: false + +examples: + - | + #include + + clock { + compatible = "gpio-gate-clock"; + clocks = <&parentclk>; + #clock-cells = <0>; + enable-gpios = <&gpio 1 GPIO_ACTIVE_HIGH>; + }; diff --git a/Documentation/devicetree/bindings/clock/ti/gate.txt b/Documentation/devicetree/bindings/clock/ti/gate.txt index b4820b1de4f0..4982615c01b9 100644 --- a/Documentation/devicetree/bindings/clock/ti/gate.txt +++ b/Documentation/devicetree/bindings/clock/ti/gate.txt @@ -10,7 +10,7 @@ will be controlled instead and the corresponding hw-ops for that is used. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.txt +[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml [3] Documentation/devicetree/bindings/clock/ti/clockdomain.txt Required properties: diff --git a/Documentation/devicetree/bindings/clock/ti/interface.txt b/Documentation/devicetree/bindings/clock/ti/interface.txt index 94ec77dc3c59..d3eb5ca92a7f 100644 --- a/Documentation/devicetree/bindings/clock/ti/interface.txt +++ b/Documentation/devicetree/bindings/clock/ti/interface.txt @@ -9,7 +9,7 @@ companion clock finding (match corresponding functional gate clock) and hardware autoidle enable / disable. [1] Documentation/devicetree/bindings/clock/clock-bindings.txt -[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.txt +[2] Documentation/devicetree/bindings/clock/gpio-gate-clock.yaml Required properties: - compatible : shall be one of: -- cgit v1.2.3 From c19edff61210eb846bf8ec44c9f87d1ca9efdfd2 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Thu, 18 Aug 2022 23:00:00 +0200 Subject: clk: move from strlcpy with unused retval to strscpy Follow the advice of the below link and prefer 'strscpy' in this subsystem. Conversion is 1:1 because the return value is not used. Generated by a coccinelle script. Link: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw@mail.gmail.com/ Signed-off-by: Wolfram Sang Link: https://lore.kernel.org/r/20220818210000.6600-1-wsa+renesas@sang-engineering.com Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 2 +- drivers/clk/mvebu/dove-divider.c | 2 +- drivers/clk/tegra/clk-bpmp.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index 67f601a41023..a4d4bd3f5be5 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -165,7 +165,7 @@ vclkdev_alloc(struct clk_hw *hw, const char *con_id, const char *dev_fmt, cla->cl.clk_hw = hw; if (con_id) { - strlcpy(cla->con_id, con_id, sizeof(cla->con_id)); + strscpy(cla->con_id, con_id, sizeof(cla->con_id)); cla->cl.con_id = cla->con_id; } diff --git a/drivers/clk/mvebu/dove-divider.c b/drivers/clk/mvebu/dove-divider.c index 7e35c891e168..0a90452ee808 100644 --- a/drivers/clk/mvebu/dove-divider.c +++ b/drivers/clk/mvebu/dove-divider.c @@ -170,7 +170,7 @@ static struct clk *clk_register_dove_divider(struct device *dev, .num_parents = num_parents, }; - strlcpy(name, dc->name, sizeof(name)); + strscpy(name, dc->name, sizeof(name)); dc->hw.init = &init; dc->base = base; diff --git a/drivers/clk/tegra/clk-bpmp.c b/drivers/clk/tegra/clk-bpmp.c index 3748a39dae7c..d82a71f10c2c 100644 --- a/drivers/clk/tegra/clk-bpmp.c +++ b/drivers/clk/tegra/clk-bpmp.c @@ -349,7 +349,7 @@ static int tegra_bpmp_clk_get_info(struct tegra_bpmp *bpmp, unsigned int id, if (err < 0) return err; - strlcpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN); + strscpy(info->name, response.name, MRQ_CLK_NAME_MAXLEN); info->num_parents = response.num_parents; for (i = 0; i < info->num_parents; i++) -- cgit v1.2.3 From d3954b51b475c4848179cd90b24ac73684cdc76b Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Thu, 18 Aug 2022 17:01:53 +0530 Subject: clk: zynqmp: make bestdiv unsigned Divisor is always positive make it u32 *. Also the arguments passed are currently of u32 pointers. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220818113153.14431-1-shubhrajyoti.datta@amd.com Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/divider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index 422ea79907dd..05788d8325d4 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -113,7 +113,7 @@ static unsigned long zynqmp_clk_divider_recalc_rate(struct clk_hw *hw, static void zynqmp_get_divider2_val(struct clk_hw *hw, unsigned long rate, struct zynqmp_clk_divider *divider, - int *bestdiv) + u32 *bestdiv) { int div1; int div2; -- cgit v1.2.3 From dd80fb2dbf1cd8751efbe4e53e54056f56a9b115 Mon Sep 17 00:00:00 2001 From: Ian Nam Date: Tue, 10 May 2022 12:31:54 +0530 Subject: clk: zynqmp: Fix stack-out-of-bounds in strncpy` "BUG: KASAN: stack-out-of-bounds in strncpy+0x30/0x68" Linux-ATF interface is using 16 bytes of SMC payload. In case clock name is longer than 15 bytes, string terminated NULL character will not be received by Linux. Add explicit NULL character at last byte to fix issues when clock name is longer. This fixes below bug reported by KASAN: ================================================================== BUG: KASAN: stack-out-of-bounds in strncpy+0x30/0x68 Read of size 1 at addr ffff0008c89a7410 by task swapper/0/1 CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.4.0-00396-g81ef9e7-dirty #3 Hardware name: Xilinx Versal vck190 Eval board revA (QSPI) (DT) Call trace: dump_backtrace+0x0/0x1e8 show_stack+0x14/0x20 dump_stack+0xd4/0x108 print_address_description.isra.0+0xbc/0x37c __kasan_report+0x144/0x198 kasan_report+0xc/0x18 __asan_load1+0x5c/0x68 strncpy+0x30/0x68 zynqmp_clock_probe+0x238/0x7b8 platform_drv_probe+0x6c/0xc8 really_probe+0x14c/0x418 driver_probe_device+0x74/0x130 __device_attach_driver+0xc4/0xe8 bus_for_each_drv+0xec/0x150 __device_attach+0x160/0x1d8 device_initial_probe+0x10/0x18 bus_probe_device+0xe0/0xf0 device_add+0x528/0x950 of_device_add+0x5c/0x80 of_platform_device_create_pdata+0x120/0x168 of_platform_bus_create+0x244/0x4e0 of_platform_populate+0x50/0xe8 zynqmp_firmware_probe+0x370/0x3a8 platform_drv_probe+0x6c/0xc8 really_probe+0x14c/0x418 driver_probe_device+0x74/0x130 device_driver_attach+0x94/0xa0 __driver_attach+0x70/0x108 bus_for_each_dev+0xe4/0x158 driver_attach+0x30/0x40 bus_add_driver+0x21c/0x2b8 driver_register+0xbc/0x1d0 __platform_driver_register+0x7c/0x88 zynqmp_firmware_driver_init+0x1c/0x24 do_one_initcall+0xa4/0x234 kernel_init_freeable+0x1b0/0x24c kernel_init+0x10/0x110 ret_from_fork+0x10/0x18 The buggy address belongs to the page: page:ffff0008f9be1c88 refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 raw: 0008d00000000000 ffff0008f9be1c90 ffff0008f9be1c90 0000000000000000 raw: 0000000000000000 0000000000000000 00000000ffffffff page dumped because: kasan: bad access detected addr ffff0008c89a7410 is located in stack of task swapper/0/1 at offset 112 in frame: zynqmp_clock_probe+0x0/0x7b8 this frame has 3 objects: [32, 44) 'response' [64, 80) 'ret_payload' [96, 112) 'name' Memory state around the buggy address: ffff0008c89a7300: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff0008c89a7380: 00 00 00 00 f1 f1 f1 f1 00 04 f2 f2 00 00 f2 f2 >ffff0008c89a7400: 00 00 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00 ^ ffff0008c89a7480: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff0008c89a7500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ================================================================== Signed-off-by: Ian Nam Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220510070154.29528-3-shubhrajyoti.datta@xilinx.com Acked-by: Michal Simek Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clkc.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index eb25303eefed..2c9da6623b84 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -710,6 +710,13 @@ static void zynqmp_get_clock_info(void) FIELD_PREP(CLK_ATTR_NODE_INDEX, i); zynqmp_pm_clock_get_name(clock[i].clk_id, &name); + + /* + * Terminate with NULL character in case name provided by firmware + * is longer and truncated due to size limit. + */ + name.name[sizeof(name.name) - 1] = '\0'; + if (!strcmp(name.name, RESERVED_CLK_NAME)) continue; strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN); -- cgit v1.2.3 From acc1c732f35bb3a26177e54cd3de27e3524426e4 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Tue, 10 May 2022 12:31:53 +0530 Subject: clk: zynqmp: Replaced strncpy() with strscpy() Replaced strncpy() with strscpy() as the clock names are supposed to be NULL terminated. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220510070154.29528-2-shubhrajyoti.datta@xilinx.com Acked-by: Michal Simek Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clkc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 2c9da6623b84..543e6e81712f 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -163,7 +163,7 @@ static int zynqmp_get_clock_name(u32 clk_id, char *clk_name) ret = zynqmp_is_valid_clock(clk_id); if (ret == 1) { - strncpy(clk_name, clock[clk_id].clk_name, MAX_NAME_LEN); + strscpy(clk_name, clock[clk_id].clk_name, MAX_NAME_LEN); return 0; } @@ -719,7 +719,7 @@ static void zynqmp_get_clock_info(void) if (!strcmp(name.name, RESERVED_CLK_NAME)) continue; - strncpy(clock[i].clk_name, name.name, MAX_NAME_LEN); + strscpy(clock[i].clk_name, name.name, MAX_NAME_LEN); } /* Get topology of all clock */ -- cgit v1.2.3 From 6ab9810cfe6c8f3d8b8750c827d7870abd3751b9 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Wed, 18 May 2022 11:23:14 +0530 Subject: clk: zynqmp: Add a check for NULL pointer Add a NULL pointer check as clk_hw_get_parent can return NULL. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220518055314.2486-1-shubhrajyoti.datta@xilinx.com Acked-by: Michal Simek Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/divider.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/clk/zynqmp/divider.c b/drivers/clk/zynqmp/divider.c index 05788d8325d4..33a3b2a22659 100644 --- a/drivers/clk/zynqmp/divider.c +++ b/drivers/clk/zynqmp/divider.c @@ -120,10 +120,13 @@ static void zynqmp_get_divider2_val(struct clk_hw *hw, long error = LONG_MAX; unsigned long div1_prate; struct clk_hw *div1_parent_hw; + struct zynqmp_clk_divider *pdivider; struct clk_hw *div2_parent_hw = clk_hw_get_parent(hw); - struct zynqmp_clk_divider *pdivider = - to_zynqmp_clk_divider(div2_parent_hw); + if (!div2_parent_hw) + return; + + pdivider = to_zynqmp_clk_divider(div2_parent_hw); if (!pdivider) return; -- cgit v1.2.3 From 8bdb15cd05d4365dfb75978d885328ebdeb5875e Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Wed, 6 Apr 2022 14:52:11 +0530 Subject: clk: zynqmp: Check the return type zynqmp_pm_query_data Check the return type of zynqmp_pm_query_data(qdata, ret_payload); Addresses-Coverity: Event check_return Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220406092211.19017-1-shubhrajyoti.datta@xilinx.com Acked-by: Michal Simek Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/clkc.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/clk/zynqmp/clkc.c b/drivers/clk/zynqmp/clkc.c index 543e6e81712f..5636ff1ce552 100644 --- a/drivers/clk/zynqmp/clkc.c +++ b/drivers/clk/zynqmp/clkc.c @@ -220,18 +220,22 @@ static int zynqmp_pm_clock_get_num_clocks(u32 *nclocks) * This function is used to get name of clock specified by given * clock ID. * - * Return: Returns 0 + * Return: 0 on success else error+reason */ static int zynqmp_pm_clock_get_name(u32 clock_id, struct name_resp *response) { struct zynqmp_pm_query_data qdata = {0}; u32 ret_payload[PAYLOAD_ARG_CNT]; + int ret; qdata.qid = PM_QID_CLOCK_GET_NAME; qdata.arg1 = clock_id; - zynqmp_pm_query_data(qdata, ret_payload); + ret = zynqmp_pm_query_data(qdata, ret_payload); + if (ret) + return ret; + memcpy(response, ret_payload, sizeof(*response)); return 0; -- cgit v1.2.3 From 56c78cb1f00a9dde8cd762131ce8f4c5eb046fbb Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Mon, 23 May 2022 18:26:08 +0400 Subject: clk: tegra: Fix refcount leak in tegra210_clock_init of_find_matching_node() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: 6b301a059eb2 ("clk: tegra: Add support for Tegra210 clocks") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220523142608.65074-1-linmq006@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra210.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/tegra/clk-tegra210.c b/drivers/clk/tegra/clk-tegra210.c index b9099012dc7b..499f999e91e1 100644 --- a/drivers/clk/tegra/clk-tegra210.c +++ b/drivers/clk/tegra/clk-tegra210.c @@ -3748,6 +3748,7 @@ static void __init tegra210_clock_init(struct device_node *np) } pmc_base = of_iomap(node, 0); + of_node_put(node); if (!pmc_base) { pr_err("Can't map pmc registers\n"); WARN_ON(1); -- cgit v1.2.3 From db16a80c76ea395766913082b1e3f939dde29b2c Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Mon, 23 May 2022 18:38:34 +0400 Subject: clk: tegra: Fix refcount leak in tegra114_clock_init of_find_matching_node() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: 2cb5efefd6f7 ("clk: tegra: Implement clocks for Tegra114") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220523143834.7587-1-linmq006@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra114.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c index ef718c4b3826..f7405a58877e 100644 --- a/drivers/clk/tegra/clk-tegra114.c +++ b/drivers/clk/tegra/clk-tegra114.c @@ -1317,6 +1317,7 @@ static void __init tegra114_clock_init(struct device_node *np) } pmc_base = of_iomap(node, 0); + of_node_put(node); if (!pmc_base) { pr_err("Can't map pmc registers\n"); WARN_ON(1); -- cgit v1.2.3 From 4e343bafe03ff68a62f48f8235cf98f2c685468b Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Mon, 23 May 2022 19:28:11 +0400 Subject: clk: tegra20: Fix refcount leak in tegra20_clock_init of_find_matching_node() returns a node pointer with refcount incremented, we should use of_node_put() on it when not need anymore. Add missing of_node_put() to avoid refcount leak. Fixes: 37c26a906527 ("clk: tegra: add clock support for Tegra20") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220523152811.19692-1-linmq006@gmail.com Signed-off-by: Stephen Boyd --- drivers/clk/tegra/clk-tegra20.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index be3c33441cfc..8a4514f6d503 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c @@ -1131,6 +1131,7 @@ static void __init tegra20_clock_init(struct device_node *np) } pmc_base = of_iomap(node, 0); + of_node_put(node); if (!pmc_base) { pr_err("Can't map pmc registers\n"); BUG(); -- cgit v1.2.3 From 35dbdcac516977cf88ccdd211827874b87077bb6 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 11 Apr 2022 15:34:39 +0530 Subject: dt-bindings: add documentation of xilinx clocking wizard Add the devicetree binding for the xilinx clocking wizard. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220411100443.15132-2-shubhrajyoti.datta@xilinx.com Reviewed-by: Rob Herring Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- .../bindings/clock/xlnx,clocking-wizard.yaml | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml diff --git a/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml new file mode 100644 index 000000000000..634b7b964606 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/xlnx,clocking-wizard.yaml @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: "http://devicetree.org/schemas/clock/xlnx,clocking-wizard.yaml#" +$schema: "http://devicetree.org/meta-schemas/core.yaml#" + +title: Xilinx clocking wizard + +maintainers: + - Shubhrajyoti Datta + +description: + The clocking wizard is a soft ip clocking block of Xilinx versal. It + reads required input clock frequencies from the devicetree and acts as clock + clock output. + +properties: + compatible: + enum: + - xlnx,clocking-wizard + - xlnx,clocking-wizard-v5.2 + - xlnx,clocking-wizard-v6.0 + + + reg: + maxItems: 1 + + "#clock-cells": + const: 1 + + clocks: + items: + - description: clock input + - description: axi clock + + clock-names: + items: + - const: clk_in1 + - const: s_axi_aclk + + + xlnx,speed-grade: + $ref: /schemas/types.yaml#/definitions/uint32 + enum: [1, 2, 3] + description: + Speed grade of the device. Higher the speed grade faster is the FPGA device. + + xlnx,nr-outputs: + $ref: /schemas/types.yaml#/definitions/uint32 + minimum: 1 + maximum: 8 + description: + Number of outputs. + +required: + - compatible + - reg + - "#clock-cells" + - clocks + - clock-names + - xlnx,speed-grade + - xlnx,nr-outputs + +additionalProperties: false + +examples: + - | + clock-controller@b0000000 { + compatible = "xlnx,clocking-wizard"; + reg = <0xb0000000 0x10000>; + #clock-cells = <1>; + xlnx,speed-grade = <1>; + xlnx,nr-outputs = <6>; + clock-names = "clk_in1", "s_axi_aclk"; + clocks = <&clkc 15>, <&clkc 15>; + }; +... -- cgit v1.2.3 From c822490f52da4ae3ee5bf2b809c765ea9d8143f9 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 11 Apr 2022 15:34:40 +0530 Subject: clk: clocking-wizard: Move clocking-wizard out Add clocking wizard driver to clk. And delete the driver from the staging as it is in drivers/clk. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220411100443.15132-3-shubhrajyoti.datta@xilinx.com Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/Kconfig | 11 + drivers/clk/xilinx/Makefile | 1 + drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 635 +++++++++++++++++++++ drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/clocking-wizard/Kconfig | 10 - drivers/staging/clocking-wizard/Makefile | 2 - drivers/staging/clocking-wizard/TODO | 13 - .../clocking-wizard/clk-xlnx-clock-wizard.c | 634 -------------------- drivers/staging/clocking-wizard/dt-binding.txt | 30 - 10 files changed, 647 insertions(+), 692 deletions(-) create mode 100644 drivers/clk/xilinx/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/Kconfig delete mode 100644 drivers/staging/clocking-wizard/Makefile delete mode 100644 drivers/staging/clocking-wizard/TODO delete mode 100644 drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c delete mode 100644 drivers/staging/clocking-wizard/dt-binding.txt diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig index 5224114176ed..5b99ecfd2f06 100644 --- a/drivers/clk/xilinx/Kconfig +++ b/drivers/clk/xilinx/Kconfig @@ -17,3 +17,14 @@ config XILINX_VCU To compile this driver as a module, choose M here: the module will be called xlnx_vcu. +config COMMON_CLK_XLNX_CLKWZRD + tristate "Xilinx Clocking Wizard" + depends on COMMON_CLK && OF + help + Support for the Xilinx Clocking Wizard IP core clock generator. + Adds support for clocking wizard and compatible. + This driver supports the Xilinx clocking wizard programmable clock + synthesizer. The number of output is configurable in the design. + + If unsure, say N. + diff --git a/drivers/clk/xilinx/Makefile b/drivers/clk/xilinx/Makefile index dee8fd51e303..7ac1789c6b1b 100644 --- a/drivers/clk/xilinx/Makefile +++ b/drivers/clk/xilinx/Makefile @@ -1,2 +1,3 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_XILINX_VCU) += xlnx_vcu.o +obj-$(CONFIG_COMMON_CLK_XLNX_CLKWZRD) += clk-xlnx-clock-wizard.o diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c new file mode 100644 index 000000000000..ec377f0d569b --- /dev/null +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -0,0 +1,635 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Xilinx 'Clocking Wizard' driver + * + * Copyright (C) 2013 - 2021 Xilinx + * + * Sören Brinkmann + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define WZRD_NUM_OUTPUTS 7 +#define WZRD_ACLK_MAX_FREQ 250000000UL + +#define WZRD_CLK_CFG_REG(n) (0x200 + 4 * (n)) + +#define WZRD_CLKOUT0_FRAC_EN BIT(18) +#define WZRD_CLKFBOUT_FRAC_EN BIT(26) + +#define WZRD_CLKFBOUT_MULT_SHIFT 8 +#define WZRD_CLKFBOUT_MULT_MASK (0xff << WZRD_CLKFBOUT_MULT_SHIFT) +#define WZRD_CLKFBOUT_FRAC_SHIFT 16 +#define WZRD_CLKFBOUT_FRAC_MASK (0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT) +#define WZRD_DIVCLK_DIVIDE_SHIFT 0 +#define WZRD_DIVCLK_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_DIVIDE_SHIFT 0 +#define WZRD_CLKOUT_DIVIDE_WIDTH 8 +#define WZRD_CLKOUT_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT) +#define WZRD_CLKOUT_FRAC_SHIFT 8 +#define WZRD_CLKOUT_FRAC_MASK 0x3ff + +#define WZRD_DR_MAX_INT_DIV_VALUE 255 +#define WZRD_DR_STATUS_REG_OFFSET 0x04 +#define WZRD_DR_LOCK_BIT_MASK 0x00000001 +#define WZRD_DR_INIT_REG_OFFSET 0x25C +#define WZRD_DR_DIV_TO_PHASE_OFFSET 4 +#define WZRD_DR_BEGIN_DYNA_RECONF 0x03 + +#define WZRD_USEC_POLL 10 +#define WZRD_TIMEOUT_POLL 1000 +/* Get the mask from width */ +#define div_mask(width) ((1 << (width)) - 1) + +/* Extract divider instance from clock hardware instance */ +#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw) + +enum clk_wzrd_int_clks { + wzrd_clk_mul, + wzrd_clk_mul_div, + wzrd_clk_mul_frac, + wzrd_clk_int_max +}; + +/** + * struct clk_wzrd - Clock wizard private data structure + * + * @clk_data: Clock data + * @nb: Notifier block + * @base: Memory base + * @clk_in1: Handle to input clock 'clk_in1' + * @axi_clk: Handle to input clock 's_axi_aclk' + * @clks_internal: Internal clocks + * @clkout: Output clocks + * @speed_grade: Speed grade of the device + * @suspended: Flag indicating power state of the device + */ +struct clk_wzrd { + struct clk_onecell_data clk_data; + struct notifier_block nb; + void __iomem *base; + struct clk *clk_in1; + struct clk *axi_clk; + struct clk *clks_internal[wzrd_clk_int_max]; + struct clk *clkout[WZRD_NUM_OUTPUTS]; + unsigned int speed_grade; + bool suspended; +}; + +/** + * struct clk_wzrd_divider - clock divider specific to clk_wzrd + * + * @hw: handle between common and hardware-specific interfaces + * @base: base address of register containing the divider + * @offset: offset address of register containing the divider + * @shift: shift to the divider bit field + * @width: width of the divider bit field + * @flags: clk_wzrd divider flags + * @table: array of value/divider pairs, last entry should have div = 0 + * @lock: register lock + */ +struct clk_wzrd_divider { + struct clk_hw hw; + void __iomem *base; + u16 offset; + u8 shift; + u8 width; + u8 flags; + const struct clk_div_table *table; + spinlock_t *lock; /* divider lock */ +}; + +#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) + +/* maximum frequencies for input/output clocks per speed grade */ +static const unsigned long clk_wzrd_max_freq[] = { + 800000000UL, + 933000000UL, + 1066000000UL +}; + +/* spin lock variable for clk_wzrd */ +static DEFINE_SPINLOCK(clkwzrd_lock); + +static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + unsigned int val; + + val = readl(div_addr) >> divider->shift; + val &= div_mask(divider->width); + + return divider_recalc_rate(hw, parent_rate, val, divider->table, + divider->flags, divider->width); +} + +static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int err; + u32 value; + unsigned long flags = 0; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + if (divider->lock) + spin_lock_irqsave(divider->lock, flags); + else + __acquire(divider->lock); + + value = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Cap the value to max */ + min_t(u32, value, WZRD_DR_MAX_INT_DIV_VALUE); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, + value, value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + if (err) + goto err_reconfig; + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, + value, value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); +err_reconfig: + if (divider->lock) + spin_unlock_irqrestore(divider->lock, flags); + else + __release(divider->lock); + return err; +} + +static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + u8 div; + + /* + * since we don't change parent rate we just round rate to closest + * achievable + */ + div = DIV_ROUND_CLOSEST(*prate, rate); + + return *prate / div; +} + +static const struct clk_ops clk_wzrd_clk_divider_ops = { + .round_rate = clk_wzrd_round_rate, + .set_rate = clk_wzrd_dynamic_reconfig, + .recalc_rate = clk_wzrd_recalc_rate, +}; + +static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, + unsigned long parent_rate) +{ + unsigned int val; + u32 div, frac; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + val = readl(div_addr); + div = val & div_mask(divider->width); + frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK; + + return mult_frac(parent_rate, 1000, (div * 1000) + frac); +} + +static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + int err; + u32 value, pre; + unsigned long rate_div, f, clockout0_div; + struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); + void __iomem *div_addr = divider->base + divider->offset; + + rate_div = ((parent_rate * 1000) / rate); + clockout0_div = rate_div / 1000; + + pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); + f = (u32)(pre - (clockout0_div * 1000)); + f = f & WZRD_CLKOUT_FRAC_MASK; + f = f << WZRD_CLKOUT_DIVIDE_WIDTH; + + value = (f | (clockout0_div & WZRD_CLKOUT_DIVIDE_MASK)); + + /* Set divisor and clear phase offset */ + writel(value, div_addr); + writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); + + /* Check status register */ + err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); + if (err) + return err; + + /* Initiate reconfiguration */ + writel(WZRD_DR_BEGIN_DYNA_RECONF, + divider->base + WZRD_DR_INIT_REG_OFFSET); + + /* Check status register */ + return readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, + value & WZRD_DR_LOCK_BIT_MASK, + WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); +} + +static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + return rate; +} + +static const struct clk_ops clk_wzrd_clk_divider_ops_f = { + .round_rate = clk_wzrd_round_rate_f, + .set_rate = clk_wzrd_dynamic_reconfig_f, + .recalc_rate = clk_wzrd_recalc_ratef, +}; + +static struct clk *clk_wzrd_register_divf(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *base, u16 offset, + u8 shift, u8 width, + u8 clk_divider_flags, + const struct clk_div_table *table, + spinlock_t *lock) +{ + struct clk_wzrd_divider *div; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + init.name = name; + + init.ops = &clk_wzrd_clk_divider_ops_f; + + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + div->base = base; + div->offset = offset; + div->shift = shift; + div->width = width; + div->flags = clk_divider_flags; + div->lock = lock; + div->hw.init = &init; + div->table = table; + + hw = &div->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) + return ERR_PTR(ret); + + return hw->clk; +} + +static struct clk *clk_wzrd_register_divider(struct device *dev, + const char *name, + const char *parent_name, + unsigned long flags, + void __iomem *base, u16 offset, + u8 shift, u8 width, + u8 clk_divider_flags, + const struct clk_div_table *table, + spinlock_t *lock) +{ + struct clk_wzrd_divider *div; + struct clk_hw *hw; + struct clk_init_data init; + int ret; + + div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); + if (!div) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.ops = &clk_wzrd_clk_divider_ops; + init.flags = flags; + init.parent_names = &parent_name; + init.num_parents = 1; + + div->base = base; + div->offset = offset; + div->shift = shift; + div->width = width; + div->flags = clk_divider_flags; + div->lock = lock; + div->hw.init = &init; + div->table = table; + + hw = &div->hw; + ret = devm_clk_hw_register(dev, hw); + if (ret) + hw = ERR_PTR(ret); + + return hw->clk; +} + +static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, + void *data) +{ + unsigned long max; + struct clk_notifier_data *ndata = data; + struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb); + + if (clk_wzrd->suspended) + return NOTIFY_OK; + + if (ndata->clk == clk_wzrd->clk_in1) + max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; + else if (ndata->clk == clk_wzrd->axi_clk) + max = WZRD_ACLK_MAX_FREQ; + else + return NOTIFY_DONE; /* should never happen */ + + switch (event) { + case PRE_RATE_CHANGE: + if (ndata->new_rate > max) + return NOTIFY_BAD; + return NOTIFY_OK; + case POST_RATE_CHANGE: + case ABORT_RATE_CHANGE: + default: + return NOTIFY_DONE; + } +} + +static int __maybe_unused clk_wzrd_suspend(struct device *dev) +{ + struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev); + + clk_disable_unprepare(clk_wzrd->axi_clk); + clk_wzrd->suspended = true; + + return 0; +} + +static int __maybe_unused clk_wzrd_resume(struct device *dev) +{ + int ret; + struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev); + + ret = clk_prepare_enable(clk_wzrd->axi_clk); + if (ret) { + dev_err(dev, "unable to enable s_axi_aclk\n"); + return ret; + } + + clk_wzrd->suspended = false; + + return 0; +} + +static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend, + clk_wzrd_resume); + +static int clk_wzrd_probe(struct platform_device *pdev) +{ + int i, ret; + u32 reg, reg_f, mult; + unsigned long rate; + const char *clk_name; + void __iomem *ctrl_reg; + struct clk_wzrd *clk_wzrd; + struct device_node *np = pdev->dev.of_node; + int nr_outputs; + unsigned long flags = 0; + + clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); + if (!clk_wzrd) + return -ENOMEM; + platform_set_drvdata(pdev, clk_wzrd); + + clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(clk_wzrd->base)) + return PTR_ERR(clk_wzrd->base); + + ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade); + if (!ret) { + if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) { + dev_warn(&pdev->dev, "invalid speed grade '%d'\n", + clk_wzrd->speed_grade); + clk_wzrd->speed_grade = 0; + } + } + + clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1"); + if (IS_ERR(clk_wzrd->clk_in1)) { + if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER)) + dev_err(&pdev->dev, "clk_in1 not found\n"); + return PTR_ERR(clk_wzrd->clk_in1); + } + + clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); + if (IS_ERR(clk_wzrd->axi_clk)) { + if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER)) + dev_err(&pdev->dev, "s_axi_aclk not found\n"); + return PTR_ERR(clk_wzrd->axi_clk); + } + ret = clk_prepare_enable(clk_wzrd->axi_clk); + if (ret) { + dev_err(&pdev->dev, "enabling s_axi_aclk failed\n"); + return ret; + } + rate = clk_get_rate(clk_wzrd->axi_clk); + if (rate > WZRD_ACLK_MAX_FREQ) { + dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n", + rate); + ret = -EINVAL; + goto err_disable_clk; + } + + reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)); + reg_f = reg & WZRD_CLKFBOUT_FRAC_MASK; + reg_f = reg_f >> WZRD_CLKFBOUT_FRAC_SHIFT; + + reg = reg & WZRD_CLKFBOUT_MULT_MASK; + reg = reg >> WZRD_CLKFBOUT_MULT_SHIFT; + mult = (reg * 1000) + reg_f; + clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(&pdev->dev)); + if (!clk_name) { + ret = -ENOMEM; + goto err_disable_clk; + } + + ret = of_property_read_u32(np, "nr-outputs", &nr_outputs); + if (ret || nr_outputs > WZRD_NUM_OUTPUTS) { + ret = -EINVAL; + goto err_disable_clk; + } + if (nr_outputs == 1) + flags = CLK_SET_RATE_PARENT; + + clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor + (&pdev->dev, clk_name, + __clk_get_name(clk_wzrd->clk_in1), + 0, mult, 1000); + if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) { + dev_err(&pdev->dev, "unable to register fixed-factor clock\n"); + ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]); + goto err_disable_clk; + } + + clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); + if (!clk_name) { + ret = -ENOMEM; + goto err_rm_int_clk; + } + + ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0); + /* register div */ + clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider + (&pdev->dev, clk_name, + __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), + flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED | + CLK_DIVIDER_ALLOW_ZERO, &clkwzrd_lock); + if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) { + dev_err(&pdev->dev, "unable to register divider clock\n"); + ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]); + goto err_rm_int_clk; + } + + /* register div per output */ + for (i = nr_outputs - 1; i >= 0 ; i--) { + const char *clkout_name; + + clkout_name = kasprintf(GFP_KERNEL, "%s_out%d", dev_name(&pdev->dev), i); + if (!clkout_name) { + ret = -ENOMEM; + goto err_rm_int_clk; + } + + if (!i) + clk_wzrd->clkout[i] = clk_wzrd_register_divf + (&pdev->dev, clkout_name, + clk_name, flags, + clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), + WZRD_CLKOUT_DIVIDE_SHIFT, + WZRD_CLKOUT_DIVIDE_WIDTH, + CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + NULL, &clkwzrd_lock); + else + clk_wzrd->clkout[i] = clk_wzrd_register_divider + (&pdev->dev, clkout_name, + clk_name, 0, + clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), + WZRD_CLKOUT_DIVIDE_SHIFT, + WZRD_CLKOUT_DIVIDE_WIDTH, + CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, + NULL, &clkwzrd_lock); + if (IS_ERR(clk_wzrd->clkout[i])) { + int j; + + for (j = i + 1; j < nr_outputs; j++) + clk_unregister(clk_wzrd->clkout[j]); + dev_err(&pdev->dev, + "unable to register divider clock\n"); + ret = PTR_ERR(clk_wzrd->clkout[i]); + goto err_rm_int_clks; + } + } + + kfree(clk_name); + + clk_wzrd->clk_data.clks = clk_wzrd->clkout; + clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data); + + if (clk_wzrd->speed_grade) { + clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier; + + ret = clk_notifier_register(clk_wzrd->clk_in1, + &clk_wzrd->nb); + if (ret) + dev_warn(&pdev->dev, + "unable to register clock notifier\n"); + + ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb); + if (ret) + dev_warn(&pdev->dev, + "unable to register clock notifier\n"); + } + + return 0; + +err_rm_int_clks: + clk_unregister(clk_wzrd->clks_internal[1]); +err_rm_int_clk: + kfree(clk_name); + clk_unregister(clk_wzrd->clks_internal[0]); +err_disable_clk: + clk_disable_unprepare(clk_wzrd->axi_clk); + + return ret; +} + +static int clk_wzrd_remove(struct platform_device *pdev) +{ + int i; + struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev); + + of_clk_del_provider(pdev->dev.of_node); + + for (i = 0; i < WZRD_NUM_OUTPUTS; i++) + clk_unregister(clk_wzrd->clkout[i]); + for (i = 0; i < wzrd_clk_int_max; i++) + clk_unregister(clk_wzrd->clks_internal[i]); + + if (clk_wzrd->speed_grade) { + clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb); + clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb); + } + + clk_disable_unprepare(clk_wzrd->axi_clk); + + return 0; +} + +static const struct of_device_id clk_wzrd_ids[] = { + { .compatible = "xlnx,clocking-wizard" }, + { }, +}; +MODULE_DEVICE_TABLE(of, clk_wzrd_ids); + +static struct platform_driver clk_wzrd_driver = { + .driver = { + .name = "clk-wizard", + .of_match_table = clk_wzrd_ids, + .pm = &clk_wzrd_dev_pm_ops, + }, + .probe = clk_wzrd_probe, + .remove = clk_wzrd_remove, +}; +module_platform_driver(clk_wzrd_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Soeren Brinkmann - Sören Brinkmann diff --git a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c b/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c deleted file mode 100644 index 39367712ef54..000000000000 --- a/drivers/staging/clocking-wizard/clk-xlnx-clock-wizard.c +++ /dev/null @@ -1,634 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0 -/* - * Xilinx 'Clocking Wizard' driver - * - * Copyright (C) 2013 - 2014 Xilinx - * - * Sören Brinkmann - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define WZRD_NUM_OUTPUTS 7 -#define WZRD_ACLK_MAX_FREQ 250000000UL - -#define WZRD_CLK_CFG_REG(n) (0x200 + 4 * (n)) - -#define WZRD_CLKOUT0_FRAC_EN BIT(18) -#define WZRD_CLKFBOUT_FRAC_EN BIT(26) - -#define WZRD_CLKFBOUT_MULT_SHIFT 8 -#define WZRD_CLKFBOUT_MULT_MASK (0xff << WZRD_CLKFBOUT_MULT_SHIFT) -#define WZRD_CLKFBOUT_FRAC_SHIFT 16 -#define WZRD_CLKFBOUT_FRAC_MASK (0x3ff << WZRD_CLKFBOUT_FRAC_SHIFT) -#define WZRD_DIVCLK_DIVIDE_SHIFT 0 -#define WZRD_DIVCLK_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT) -#define WZRD_CLKOUT_DIVIDE_SHIFT 0 -#define WZRD_CLKOUT_DIVIDE_WIDTH 8 -#define WZRD_CLKOUT_DIVIDE_MASK (0xff << WZRD_DIVCLK_DIVIDE_SHIFT) -#define WZRD_CLKOUT_FRAC_SHIFT 8 -#define WZRD_CLKOUT_FRAC_MASK 0x3ff - -#define WZRD_DR_MAX_INT_DIV_VALUE 255 -#define WZRD_DR_STATUS_REG_OFFSET 0x04 -#define WZRD_DR_LOCK_BIT_MASK 0x00000001 -#define WZRD_DR_INIT_REG_OFFSET 0x25C -#define WZRD_DR_DIV_TO_PHASE_OFFSET 4 -#define WZRD_DR_BEGIN_DYNA_RECONF 0x03 - -#define WZRD_USEC_POLL 10 -#define WZRD_TIMEOUT_POLL 1000 -/* Get the mask from width */ -#define div_mask(width) ((1 << (width)) - 1) - -/* Extract divider instance from clock hardware instance */ -#define to_clk_wzrd_divider(_hw) container_of(_hw, struct clk_wzrd_divider, hw) - -enum clk_wzrd_int_clks { - wzrd_clk_mul, - wzrd_clk_mul_div, - wzrd_clk_mul_frac, - wzrd_clk_int_max -}; - -/** - * struct clk_wzrd - Clock wizard private data structure - * - * @clk_data: Clock data - * @nb: Notifier block - * @base: Memory base - * @clk_in1: Handle to input clock 'clk_in1' - * @axi_clk: Handle to input clock 's_axi_aclk' - * @clks_internal: Internal clocks - * @clkout: Output clocks - * @speed_grade: Speed grade of the device - * @suspended: Flag indicating power state of the device - */ -struct clk_wzrd { - struct clk_onecell_data clk_data; - struct notifier_block nb; - void __iomem *base; - struct clk *clk_in1; - struct clk *axi_clk; - struct clk *clks_internal[wzrd_clk_int_max]; - struct clk *clkout[WZRD_NUM_OUTPUTS]; - unsigned int speed_grade; - bool suspended; -}; - -/** - * struct clk_wzrd_divider - clock divider specific to clk_wzrd - * - * @hw: handle between common and hardware-specific interfaces - * @base: base address of register containing the divider - * @offset: offset address of register containing the divider - * @shift: shift to the divider bit field - * @width: width of the divider bit field - * @flags: clk_wzrd divider flags - * @table: array of value/divider pairs, last entry should have div = 0 - * @lock: register lock - */ -struct clk_wzrd_divider { - struct clk_hw hw; - void __iomem *base; - u16 offset; - u8 shift; - u8 width; - u8 flags; - const struct clk_div_table *table; - spinlock_t *lock; /* divider lock */ -}; - -#define to_clk_wzrd(_nb) container_of(_nb, struct clk_wzrd, nb) - -/* maximum frequencies for input/output clocks per speed grade */ -static const unsigned long clk_wzrd_max_freq[] = { - 800000000UL, - 933000000UL, - 1066000000UL -}; - -/* spin lock variable for clk_wzrd */ -static DEFINE_SPINLOCK(clkwzrd_lock); - -static unsigned long clk_wzrd_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) -{ - struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); - void __iomem *div_addr = divider->base + divider->offset; - unsigned int val; - - val = readl(div_addr) >> divider->shift; - val &= div_mask(divider->width); - - return divider_recalc_rate(hw, parent_rate, val, divider->table, - divider->flags, divider->width); -} - -static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int err; - u32 value; - unsigned long flags = 0; - struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); - void __iomem *div_addr = divider->base + divider->offset; - - if (divider->lock) - spin_lock_irqsave(divider->lock, flags); - else - __acquire(divider->lock); - - value = DIV_ROUND_CLOSEST(parent_rate, rate); - - /* Cap the value to max */ - min_t(u32, value, WZRD_DR_MAX_INT_DIV_VALUE); - - /* Set divisor and clear phase offset */ - writel(value, div_addr); - writel(0x00, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); - - /* Check status register */ - err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, - value, value & WZRD_DR_LOCK_BIT_MASK, - WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); - if (err) - goto err_reconfig; - - /* Initiate reconfiguration */ - writel(WZRD_DR_BEGIN_DYNA_RECONF, - divider->base + WZRD_DR_INIT_REG_OFFSET); - - /* Check status register */ - err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, - value, value & WZRD_DR_LOCK_BIT_MASK, - WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); -err_reconfig: - if (divider->lock) - spin_unlock_irqrestore(divider->lock, flags); - else - __release(divider->lock); - return err; -} - -static long clk_wzrd_round_rate(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - u8 div; - - /* - * since we don't change parent rate we just round rate to closest - * achievable - */ - div = DIV_ROUND_CLOSEST(*prate, rate); - - return *prate / div; -} - -static const struct clk_ops clk_wzrd_clk_divider_ops = { - .round_rate = clk_wzrd_round_rate, - .set_rate = clk_wzrd_dynamic_reconfig, - .recalc_rate = clk_wzrd_recalc_rate, -}; - -static unsigned long clk_wzrd_recalc_ratef(struct clk_hw *hw, - unsigned long parent_rate) -{ - unsigned int val; - u32 div, frac; - struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); - void __iomem *div_addr = divider->base + divider->offset; - - val = readl(div_addr); - div = val & div_mask(divider->width); - frac = (val >> WZRD_CLKOUT_FRAC_SHIFT) & WZRD_CLKOUT_FRAC_MASK; - - return mult_frac(parent_rate, 1000, (div * 1000) + frac); -} - -static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, - unsigned long parent_rate) -{ - int err; - u32 value, pre; - unsigned long rate_div, f, clockout0_div; - struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); - void __iomem *div_addr = divider->base + divider->offset; - - rate_div = ((parent_rate * 1000) / rate); - clockout0_div = rate_div / 1000; - - pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); - f = (u32)(pre - (clockout0_div * 1000)); - f = f & WZRD_CLKOUT_FRAC_MASK; - f = f << WZRD_CLKOUT_DIVIDE_WIDTH; - - value = (f | (clockout0_div & WZRD_CLKOUT_DIVIDE_MASK)); - - /* Set divisor and clear phase offset */ - writel(value, div_addr); - writel(0x0, div_addr + WZRD_DR_DIV_TO_PHASE_OFFSET); - - /* Check status register */ - err = readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, - value & WZRD_DR_LOCK_BIT_MASK, - WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); - if (err) - return err; - - /* Initiate reconfiguration */ - writel(WZRD_DR_BEGIN_DYNA_RECONF, - divider->base + WZRD_DR_INIT_REG_OFFSET); - - /* Check status register */ - return readl_poll_timeout(divider->base + WZRD_DR_STATUS_REG_OFFSET, value, - value & WZRD_DR_LOCK_BIT_MASK, - WZRD_USEC_POLL, WZRD_TIMEOUT_POLL); -} - -static long clk_wzrd_round_rate_f(struct clk_hw *hw, unsigned long rate, - unsigned long *prate) -{ - return rate; -} - -static const struct clk_ops clk_wzrd_clk_divider_ops_f = { - .round_rate = clk_wzrd_round_rate_f, - .set_rate = clk_wzrd_dynamic_reconfig_f, - .recalc_rate = clk_wzrd_recalc_ratef, -}; - -static struct clk *clk_wzrd_register_divf(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags, - void __iomem *base, u16 offset, - u8 shift, u8 width, - u8 clk_divider_flags, - const struct clk_div_table *table, - spinlock_t *lock) -{ - struct clk_wzrd_divider *div; - struct clk_hw *hw; - struct clk_init_data init; - int ret; - - div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); - if (!div) - return ERR_PTR(-ENOMEM); - - init.name = name; - - init.ops = &clk_wzrd_clk_divider_ops_f; - - init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; - - div->base = base; - div->offset = offset; - div->shift = shift; - div->width = width; - div->flags = clk_divider_flags; - div->lock = lock; - div->hw.init = &init; - div->table = table; - - hw = &div->hw; - ret = devm_clk_hw_register(dev, hw); - if (ret) - return ERR_PTR(ret); - - return hw->clk; -} - -static struct clk *clk_wzrd_register_divider(struct device *dev, - const char *name, - const char *parent_name, - unsigned long flags, - void __iomem *base, u16 offset, - u8 shift, u8 width, - u8 clk_divider_flags, - const struct clk_div_table *table, - spinlock_t *lock) -{ - struct clk_wzrd_divider *div; - struct clk_hw *hw; - struct clk_init_data init; - int ret; - - div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL); - if (!div) - return ERR_PTR(-ENOMEM); - - init.name = name; - init.ops = &clk_wzrd_clk_divider_ops; - init.flags = flags; - init.parent_names = &parent_name; - init.num_parents = 1; - - div->base = base; - div->offset = offset; - div->shift = shift; - div->width = width; - div->flags = clk_divider_flags; - div->lock = lock; - div->hw.init = &init; - div->table = table; - - hw = &div->hw; - ret = devm_clk_hw_register(dev, hw); - if (ret) - hw = ERR_PTR(ret); - - return hw->clk; -} - -static int clk_wzrd_clk_notifier(struct notifier_block *nb, unsigned long event, - void *data) -{ - unsigned long max; - struct clk_notifier_data *ndata = data; - struct clk_wzrd *clk_wzrd = to_clk_wzrd(nb); - - if (clk_wzrd->suspended) - return NOTIFY_OK; - - if (ndata->clk == clk_wzrd->clk_in1) - max = clk_wzrd_max_freq[clk_wzrd->speed_grade - 1]; - else if (ndata->clk == clk_wzrd->axi_clk) - max = WZRD_ACLK_MAX_FREQ; - else - return NOTIFY_DONE; /* should never happen */ - - switch (event) { - case PRE_RATE_CHANGE: - if (ndata->new_rate > max) - return NOTIFY_BAD; - return NOTIFY_OK; - case POST_RATE_CHANGE: - case ABORT_RATE_CHANGE: - default: - return NOTIFY_DONE; - } -} - -static int __maybe_unused clk_wzrd_suspend(struct device *dev) -{ - struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev); - - clk_disable_unprepare(clk_wzrd->axi_clk); - clk_wzrd->suspended = true; - - return 0; -} - -static int __maybe_unused clk_wzrd_resume(struct device *dev) -{ - int ret; - struct clk_wzrd *clk_wzrd = dev_get_drvdata(dev); - - ret = clk_prepare_enable(clk_wzrd->axi_clk); - if (ret) { - dev_err(dev, "unable to enable s_axi_aclk\n"); - return ret; - } - - clk_wzrd->suspended = false; - - return 0; -} - -static SIMPLE_DEV_PM_OPS(clk_wzrd_dev_pm_ops, clk_wzrd_suspend, - clk_wzrd_resume); - -static int clk_wzrd_probe(struct platform_device *pdev) -{ - int i, ret; - u32 reg, reg_f, mult; - unsigned long rate; - const char *clk_name; - void __iomem *ctrl_reg; - struct clk_wzrd *clk_wzrd; - struct device_node *np = pdev->dev.of_node; - int nr_outputs; - unsigned long flags = 0; - - clk_wzrd = devm_kzalloc(&pdev->dev, sizeof(*clk_wzrd), GFP_KERNEL); - if (!clk_wzrd) - return -ENOMEM; - platform_set_drvdata(pdev, clk_wzrd); - - clk_wzrd->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(clk_wzrd->base)) - return PTR_ERR(clk_wzrd->base); - - ret = of_property_read_u32(np, "xlnx,speed-grade", &clk_wzrd->speed_grade); - if (!ret) { - if (clk_wzrd->speed_grade < 1 || clk_wzrd->speed_grade > 3) { - dev_warn(&pdev->dev, "invalid speed grade '%d'\n", - clk_wzrd->speed_grade); - clk_wzrd->speed_grade = 0; - } - } - - clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1"); - if (IS_ERR(clk_wzrd->clk_in1)) { - if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER)) - dev_err(&pdev->dev, "clk_in1 not found\n"); - return PTR_ERR(clk_wzrd->clk_in1); - } - - clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); - if (IS_ERR(clk_wzrd->axi_clk)) { - if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER)) - dev_err(&pdev->dev, "s_axi_aclk not found\n"); - return PTR_ERR(clk_wzrd->axi_clk); - } - ret = clk_prepare_enable(clk_wzrd->axi_clk); - if (ret) { - dev_err(&pdev->dev, "enabling s_axi_aclk failed\n"); - return ret; - } - rate = clk_get_rate(clk_wzrd->axi_clk); - if (rate > WZRD_ACLK_MAX_FREQ) { - dev_err(&pdev->dev, "s_axi_aclk frequency (%lu) too high\n", - rate); - ret = -EINVAL; - goto err_disable_clk; - } - - reg = readl(clk_wzrd->base + WZRD_CLK_CFG_REG(0)); - reg_f = reg & WZRD_CLKFBOUT_FRAC_MASK; - reg_f = reg_f >> WZRD_CLKFBOUT_FRAC_SHIFT; - - reg = reg & WZRD_CLKFBOUT_MULT_MASK; - reg = reg >> WZRD_CLKFBOUT_MULT_SHIFT; - mult = (reg * 1000) + reg_f; - clk_name = kasprintf(GFP_KERNEL, "%s_mul", dev_name(&pdev->dev)); - if (!clk_name) { - ret = -ENOMEM; - goto err_disable_clk; - } - - ret = of_property_read_u32(np, "nr-outputs", &nr_outputs); - if (ret || nr_outputs > WZRD_NUM_OUTPUTS) { - ret = -EINVAL; - goto err_disable_clk; - } - if (nr_outputs == 1) - flags = CLK_SET_RATE_PARENT; - - clk_wzrd->clks_internal[wzrd_clk_mul] = clk_register_fixed_factor - (&pdev->dev, clk_name, - __clk_get_name(clk_wzrd->clk_in1), - 0, mult, 1000); - if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul])) { - dev_err(&pdev->dev, "unable to register fixed-factor clock\n"); - ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul]); - goto err_disable_clk; - } - - clk_name = kasprintf(GFP_KERNEL, "%s_mul_div", dev_name(&pdev->dev)); - if (!clk_name) { - ret = -ENOMEM; - goto err_rm_int_clk; - } - - ctrl_reg = clk_wzrd->base + WZRD_CLK_CFG_REG(0); - /* register div */ - clk_wzrd->clks_internal[wzrd_clk_mul_div] = clk_register_divider - (&pdev->dev, clk_name, - __clk_get_name(clk_wzrd->clks_internal[wzrd_clk_mul]), - flags, ctrl_reg, 0, 8, CLK_DIVIDER_ONE_BASED | - CLK_DIVIDER_ALLOW_ZERO, &clkwzrd_lock); - if (IS_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div])) { - dev_err(&pdev->dev, "unable to register divider clock\n"); - ret = PTR_ERR(clk_wzrd->clks_internal[wzrd_clk_mul_div]); - goto err_rm_int_clk; - } - - /* register div per output */ - for (i = nr_outputs - 1; i >= 0 ; i--) { - const char *clkout_name; - - clkout_name = kasprintf(GFP_KERNEL, "%s_out%d", dev_name(&pdev->dev), i); - if (!clkout_name) { - ret = -ENOMEM; - goto err_rm_int_clk; - } - - if (!i) - clk_wzrd->clkout[i] = clk_wzrd_register_divf - (&pdev->dev, clkout_name, - clk_name, flags, - clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), - WZRD_CLKOUT_DIVIDE_SHIFT, - WZRD_CLKOUT_DIVIDE_WIDTH, - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - NULL, &clkwzrd_lock); - else - clk_wzrd->clkout[i] = clk_wzrd_register_divider - (&pdev->dev, clkout_name, - clk_name, 0, - clk_wzrd->base, (WZRD_CLK_CFG_REG(2) + i * 12), - WZRD_CLKOUT_DIVIDE_SHIFT, - WZRD_CLKOUT_DIVIDE_WIDTH, - CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO, - NULL, &clkwzrd_lock); - if (IS_ERR(clk_wzrd->clkout[i])) { - int j; - - for (j = i + 1; j < nr_outputs; j++) - clk_unregister(clk_wzrd->clkout[j]); - dev_err(&pdev->dev, - "unable to register divider clock\n"); - ret = PTR_ERR(clk_wzrd->clkout[i]); - goto err_rm_int_clks; - } - } - - kfree(clk_name); - - clk_wzrd->clk_data.clks = clk_wzrd->clkout; - clk_wzrd->clk_data.clk_num = ARRAY_SIZE(clk_wzrd->clkout); - of_clk_add_provider(np, of_clk_src_onecell_get, &clk_wzrd->clk_data); - - if (clk_wzrd->speed_grade) { - clk_wzrd->nb.notifier_call = clk_wzrd_clk_notifier; - - ret = clk_notifier_register(clk_wzrd->clk_in1, - &clk_wzrd->nb); - if (ret) - dev_warn(&pdev->dev, - "unable to register clock notifier\n"); - - ret = clk_notifier_register(clk_wzrd->axi_clk, &clk_wzrd->nb); - if (ret) - dev_warn(&pdev->dev, - "unable to register clock notifier\n"); - } - - return 0; - -err_rm_int_clks: - clk_unregister(clk_wzrd->clks_internal[1]); -err_rm_int_clk: - kfree(clk_name); - clk_unregister(clk_wzrd->clks_internal[0]); -err_disable_clk: - clk_disable_unprepare(clk_wzrd->axi_clk); - - return ret; -} - -static int clk_wzrd_remove(struct platform_device *pdev) -{ - int i; - struct clk_wzrd *clk_wzrd = platform_get_drvdata(pdev); - - of_clk_del_provider(pdev->dev.of_node); - - for (i = 0; i < WZRD_NUM_OUTPUTS; i++) - clk_unregister(clk_wzrd->clkout[i]); - for (i = 0; i < wzrd_clk_int_max; i++) - clk_unregister(clk_wzrd->clks_internal[i]); - - if (clk_wzrd->speed_grade) { - clk_notifier_unregister(clk_wzrd->axi_clk, &clk_wzrd->nb); - clk_notifier_unregister(clk_wzrd->clk_in1, &clk_wzrd->nb); - } - - clk_disable_unprepare(clk_wzrd->axi_clk); - - return 0; -} - -static const struct of_device_id clk_wzrd_ids[] = { - { .compatible = "xlnx,clocking-wizard" }, - { }, -}; -MODULE_DEVICE_TABLE(of, clk_wzrd_ids); - -static struct platform_driver clk_wzrd_driver = { - .driver = { - .name = "clk-wizard", - .of_match_table = clk_wzrd_ids, - .pm = &clk_wzrd_dev_pm_ops, - }, - .probe = clk_wzrd_probe, - .remove = clk_wzrd_remove, -}; -module_platform_driver(clk_wzrd_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Soeren Brinkmann ; - compatible = "xlnx,clocking-wizard"; - speed-grade = <1>; - clock-names = "clk_in1", "s_axi_aclk"; - clocks = <&clkc 15>, <&clkc 15>; - clock-output-names = "clk_out0", "clk_out1", "clk_out2", - "clk_out3", "clk_out4", "clk_out5", - "clk_out6", "clk_out7"; - }; -- cgit v1.2.3 From 787ddddcbc43ab158cc15c36986c2c64b6fc84aa Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 11 Apr 2022 15:34:41 +0530 Subject: clk: clocking-wizard: Rename nr-outputs to xlnx,nr-outputs Rename nr-outputs to xlnx,output. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220411100443.15132-4-shubhrajyoti.datta@xilinx.com Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index ec377f0d569b..1e0818eb0435 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -480,7 +480,7 @@ static int clk_wzrd_probe(struct platform_device *pdev) goto err_disable_clk; } - ret = of_property_read_u32(np, "nr-outputs", &nr_outputs); + ret = of_property_read_u32(np, "xlnx,nr-outputs", &nr_outputs); if (ret || nr_outputs > WZRD_NUM_OUTPUTS) { ret = -EINVAL; goto err_disable_clk; -- cgit v1.2.3 From dd5e7431ac54e0b33f768395377fe5dbc6445f29 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 11 Apr 2022 15:34:42 +0530 Subject: clk: clocking-wizard: Fix the reconfig for 5.2 The 5.2 the reconfig is triggered by writing 7 followed by 2 to the reconfig reg. Add the same. Also 6.0 is backward compatible so it should be fine. Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220411100443.15132-5-shubhrajyoti.datta@xilinx.com Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index 1e0818eb0435..61c40e06e381 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -44,6 +44,8 @@ #define WZRD_DR_INIT_REG_OFFSET 0x25C #define WZRD_DR_DIV_TO_PHASE_OFFSET 4 #define WZRD_DR_BEGIN_DYNA_RECONF 0x03 +#define WZRD_DR_BEGIN_DYNA_RECONF_5_2 0x07 +#define WZRD_DR_BEGIN_DYNA_RECONF1_5_2 0x02 #define WZRD_USEC_POLL 10 #define WZRD_TIMEOUT_POLL 1000 @@ -165,7 +167,9 @@ static int clk_wzrd_dynamic_reconfig(struct clk_hw *hw, unsigned long rate, goto err_reconfig; /* Initiate reconfiguration */ - writel(WZRD_DR_BEGIN_DYNA_RECONF, + writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2, + divider->base + WZRD_DR_INIT_REG_OFFSET); + writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2, divider->base + WZRD_DR_INIT_REG_OFFSET); /* Check status register */ @@ -224,7 +228,7 @@ static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, struct clk_wzrd_divider *divider = to_clk_wzrd_divider(hw); void __iomem *div_addr = divider->base + divider->offset; - rate_div = ((parent_rate * 1000) / rate); + rate_div = DIV_ROUND_DOWN_ULL(parent_rate * 1000, rate); clockout0_div = rate_div / 1000; pre = DIV_ROUND_CLOSEST((parent_rate * 1000), rate); @@ -246,7 +250,9 @@ static int clk_wzrd_dynamic_reconfig_f(struct clk_hw *hw, unsigned long rate, return err; /* Initiate reconfiguration */ - writel(WZRD_DR_BEGIN_DYNA_RECONF, + writel(WZRD_DR_BEGIN_DYNA_RECONF_5_2, + divider->base + WZRD_DR_INIT_REG_OFFSET); + writel(WZRD_DR_BEGIN_DYNA_RECONF1_5_2, divider->base + WZRD_DR_INIT_REG_OFFSET); /* Check status register */ -- cgit v1.2.3 From e8db788d686a2a2e5318364a1942d01c3cc83d87 Mon Sep 17 00:00:00 2001 From: Shubhrajyoti Datta Date: Mon, 11 Apr 2022 15:34:43 +0530 Subject: clk: clocking-wizard: Update the compatible Update the compatible to indicate support for both 5.2 and 6.0 Signed-off-by: Shubhrajyoti Datta Link: https://lore.kernel.org/r/20220411100443.15132-6-shubhrajyoti.datta@xilinx.com Acked-by: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index 61c40e06e381..5b8433468cc5 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -621,6 +621,8 @@ static int clk_wzrd_remove(struct platform_device *pdev) static const struct of_device_id clk_wzrd_ids[] = { { .compatible = "xlnx,clocking-wizard" }, + { .compatible = "xlnx,clocking-wizard-v5.2" }, + { .compatible = "xlnx,clocking-wizard-v6.0" }, { }, }; MODULE_DEVICE_TABLE(of, clk_wzrd_ids); -- cgit v1.2.3 From 3378d0cc9327cb3337ffc3708e08b8010bc16c4a Mon Sep 17 00:00:00 2001 From: Jason Wang Date: Thu, 11 Aug 2022 22:00:30 +0800 Subject: clk: Fix comment typo The double `to' is duplicated in the comment, remove one. Signed-off-by: Jason Wang Link: https://lore.kernel.org/r/20220811140030.28886-1-wangborong@cdjrlc.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 7fc191c15507..275a65d146b0 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3462,7 +3462,7 @@ static void clk_core_reparent_orphans_nolock(void) /* * We need to use __clk_set_parent_before() and _after() to - * to properly migrate any prepare/enable count of the orphan + * properly migrate any prepare/enable count of the orphan * clock. This is important for CLK_IS_CRITICAL clocks, which * are enabled during init but might not have a parent yet. */ -- cgit v1.2.3 From 79806d338829b2bf903480428d8ce5aab8e2d24b Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 30 Jun 2022 18:12:04 +0300 Subject: clk: remove extra empty line Remove extra empty line. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220630151205.3935560-1-claudiu.beznea@microchip.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 275a65d146b0..141af74904e7 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -3672,7 +3672,6 @@ static int __clk_core_init(struct clk_core *core) clk_core_reparent_orphans_nolock(); - kref_init(&core->ref); out: clk_pm_runtime_put(core); -- cgit v1.2.3 From 75569a03369bfee7ee226c04915febf025585b5f Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Thu, 30 Jun 2022 18:12:05 +0300 Subject: clk: do not initialize ret There is no need to initialize ret. Signed-off-by: Claudiu Beznea Link: https://lore.kernel.org/r/20220630151205.3935560-2-claudiu.beznea@microchip.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 141af74904e7..8ccce917c260 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -2189,7 +2189,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core, { struct clk_core *top, *fail_clk; unsigned long rate; - int ret = 0; + int ret; if (!core) return 0; -- cgit v1.2.3 From 30eaf02149ecc3c5815e45d27187bf09e925071d Mon Sep 17 00:00:00 2001 From: Quanyang Wang Date: Fri, 26 Aug 2022 22:20:30 +0800 Subject: clk: zynqmp: pll: rectify rate rounding in zynqmp_pll_round_rate The function zynqmp_pll_round_rate is used to find a most appropriate PLL frequency which the hardware can generate according to the desired frequency. For example, if the desired frequency is 297MHz, considering the limited range from PS_PLL_VCO_MIN (1.5GHz) to PS_PLL_VCO_MAX (3.0GHz) of PLL, zynqmp_pll_round_rate should return 1.872GHz (297MHz * 5). There are two problems with the current code of zynqmp_pll_round_rate: 1) When the rate is below PS_PLL_VCO_MIN, it can't find a correct rate when the parameter "rate" is an integer multiple of *prate, in other words, if "f" is zero, zynqmp_pll_round_rate won't return a valid frequency which is from PS_PLL_VCO_MIN to PS_PLL_VCO_MAX. For example, *prate is 33MHz and the rate is 660MHz, zynqmp_pll_round_rate will not boost up rate and just return 660MHz, and this will cause clk_calc_new_rates failure since zynqmp_pll_round_rate returns an invalid rate out of its boundaries. 2) Even if the rate is higher than PS_PLL_VCO_MIN, there is still a risk that zynqmp_pll_round_rate returns an invalid rate because the function DIV_ROUND_CLOSEST makes some loss in the fractional part. If the parent clock *prate is 33333333Hz and we want to set the PLL rate to 1.5GHz, this function will return 1499999985Hz by using the formula below: value = *prate * DIV_ROUND_CLOSEST(rate, *prate)). This value is also invalid since it's slightly smaller than PS_PLL_VCO_MIN. because DIV_ROUND_CLOSEST makes some loss in the fractional part. Signed-off-by: Quanyang Wang Link: https://lore.kernel.org/r/20220826142030.213805-1-quanyang.wang@windriver.com Reviewed-by: Shubhrajyoti Datta Signed-off-by: Stephen Boyd --- drivers/clk/zynqmp/pll.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/drivers/clk/zynqmp/pll.c b/drivers/clk/zynqmp/pll.c index 91a6b4cc910e..0d3e1377b092 100644 --- a/drivers/clk/zynqmp/pll.c +++ b/drivers/clk/zynqmp/pll.c @@ -102,26 +102,25 @@ static long zynqmp_pll_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { u32 fbdiv; - long rate_div, f; + u32 mult, div; - /* Enable the fractional mode if needed */ - rate_div = (rate * FRAC_DIV) / *prate; - f = rate_div % FRAC_DIV; - if (f) { - if (rate > PS_PLL_VCO_MAX) { - fbdiv = rate / PS_PLL_VCO_MAX; - rate = rate / (fbdiv + 1); - } - if (rate < PS_PLL_VCO_MIN) { - fbdiv = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); - rate = rate * fbdiv; - } - return rate; + /* Let rate fall inside the range PS_PLL_VCO_MIN ~ PS_PLL_VCO_MAX */ + if (rate > PS_PLL_VCO_MAX) { + div = DIV_ROUND_UP(rate, PS_PLL_VCO_MAX); + rate = rate / div; + } + if (rate < PS_PLL_VCO_MIN) { + mult = DIV_ROUND_UP(PS_PLL_VCO_MIN, rate); + rate = rate * mult; } fbdiv = DIV_ROUND_CLOSEST(rate, *prate); - fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); - return *prate * fbdiv; + if (fbdiv < PLL_FBDIV_MIN || fbdiv > PLL_FBDIV_MAX) { + fbdiv = clamp_t(u32, fbdiv, PLL_FBDIV_MIN, PLL_FBDIV_MAX); + rate = *prate * fbdiv; + } + + return rate; } /** -- cgit v1.2.3 From 4bafca831386bd3b4b059f583b471670c19acf6a Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 25 Aug 2022 14:33:32 +0300 Subject: dt-bindings: clock: drop minItems equal to maxItems minItems, if missing, are implicitly equal to maxItems, so drop redundant piece to reduce size of code. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20220825113334.196908-3-krzysztof.kozlowski@linaro.org Reviewed-by: Alim Akhtar Reviewed-by: Laurent Pinchart Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml | 1 - .../devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml | 2 -- Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml | 1 - 3 files changed, 4 deletions(-) diff --git a/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml index 0abd6ba82dfd..82836086cac1 100644 --- a/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml +++ b/Documentation/devicetree/bindings/clock/cirrus,cs2000-cp.yaml @@ -23,7 +23,6 @@ properties: clocks: description: Common clock binding for CLK_IN, XTI/REF_CLK - minItems: 2 maxItems: 2 clock-names: diff --git a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml index 6eaabb4d82ec..81f09df7147e 100644 --- a/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml +++ b/Documentation/devicetree/bindings/clock/renesas,rcar-usb2-clock-sel.yaml @@ -47,7 +47,6 @@ properties: maxItems: 1 clocks: - minItems: 4 maxItems: 4 clock-names: @@ -64,7 +63,6 @@ properties: maxItems: 1 resets: - minItems: 2 maxItems: 2 reset-names: diff --git a/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml b/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml index 9248bfc16d48..d5296e6053a1 100644 --- a/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml +++ b/Documentation/devicetree/bindings/clock/samsung,s2mps11.yaml @@ -34,7 +34,6 @@ properties: const: 1 clock-output-names: - minItems: 3 maxItems: 3 description: Names for AP, CP and BT clocks. -- cgit v1.2.3 From 13b0452ddaa3f7d840ee16fc92aa433392a56685 Mon Sep 17 00:00:00 2001 From: Yuan Can Date: Tue, 27 Sep 2022 13:39:31 +0000 Subject: clk: clk-npcm7xx: Remove unused struct npcm7xx_clk_gate_data and npcm7xx_clk_div_fixed_data After commit 6a5898411159("clk: clk-npcm7xx: Remove unused static const tables 'npcm7xx_gates' and 'npcm7xx_divs_fx'"), no one use struct npcm7xx_clk_gate_data and struct npcm7xx_clk_div_fixed_data, so remove them. Signed-off-by: Yuan Can Link: https://lore.kernel.org/r/20220927133931.104060-1-yuancan@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-npcm7xx.c | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/drivers/clk/clk-npcm7xx.c b/drivers/clk/clk-npcm7xx.c index e677bb5a784b..e319cfa51a8a 100644 --- a/drivers/clk/clk-npcm7xx.c +++ b/drivers/clk/clk-npcm7xx.c @@ -129,20 +129,6 @@ npcm7xx_clk_register_pll(void __iomem *pllcon, const char *name, #define NPCM7XX_SECCNT (0x68) #define NPCM7XX_CNTR25M (0x6C) -struct npcm7xx_clk_gate_data { - u32 reg; - u8 bit_idx; - const char *name; - const char *parent_name; - unsigned long flags; - /* - * If this clock is exported via DT, set onecell_idx to constant - * defined in include/dt-bindings/clock/nuvoton, NPCM7XX-clock.h for - * this specific clock. Otherwise, set to -1. - */ - int onecell_idx; -}; - struct npcm7xx_clk_mux_data { u8 shift; u8 mask; @@ -160,21 +146,6 @@ struct npcm7xx_clk_mux_data { }; -struct npcm7xx_clk_div_fixed_data { - u8 mult; - u8 div; - const char *name; - const char *parent_name; - u8 clk_divider_flags; - /* - * If this clock is exported via DT, set onecell_idx to constant - * defined in include/dt-bindings/clock/nuvoton, NPCM7XX-clock.h for - * this specific clock. Otherwise, set to -1. - */ - int onecell_idx; -}; - - struct npcm7xx_clk_div_data { u32 reg; u8 shift; -- cgit v1.2.3 From fe9d25b46bc744d73491fb68f1c322910dc70437 Mon Sep 17 00:00:00 2001 From: Andi Kleen Date: Tue, 20 Sep 2022 07:58:38 +0200 Subject: clk: pistachio: Fix initconst confusion A variable pointing to const isn't const itself. It has to contain "const" keyword after "*" too. So to keep it in __initconst (and not mark properly as __initdata), add the "const" keyword exactly there. Note we need to update struct pistachio_mux too. On the other hand, the clk core already counts with "const char *const" already. [js] more explanatory commit message. Cc: Michael Turquette Cc: Stephen Boyd Cc: linux-clk@vger.kernel.org Cc: Martin Liska Signed-off-by: Andi Kleen Signed-off-by: Jiri Slaby Link: https://lore.kernel.org/r/20220920055838.22637-1-jslaby@suse.cz Signed-off-by: Stephen Boyd --- drivers/clk/pistachio/clk.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/pistachio/clk.h b/drivers/clk/pistachio/clk.h index f9c31e3a0e47..2f4ffbd98282 100644 --- a/drivers/clk/pistachio/clk.h +++ b/drivers/clk/pistachio/clk.h @@ -31,10 +31,10 @@ struct pistachio_mux { unsigned int shift; unsigned int num_parents; const char *name; - const char **parents; + const char *const *parents; }; -#define PNAME(x) static const char *x[] __initconst +#define PNAME(x) static const char *const x[] __initconst #define MUX(_id, _name, _pnames, _reg, _shift) \ { \ -- cgit v1.2.3 From 1c8934b4802d2744c97e7c97d244af967f4bf141 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 23 Jun 2022 14:57:17 +0300 Subject: clk: Remove never used devm_of_clk_del_provider() For the entire history of the devm_of_clk_del_provider) existence (since 2017) it was never used. Remove it for good. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220623115719.52683-1-andriy.shevchenko@linux.intel.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 26 -------------------------- include/linux/clk-provider.h | 4 ++-- 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 8ccce917c260..3c869191b258 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4750,32 +4750,6 @@ void of_clk_del_provider(struct device_node *np) } EXPORT_SYMBOL_GPL(of_clk_del_provider); -static int devm_clk_provider_match(struct device *dev, void *res, void *data) -{ - struct device_node **np = res; - - if (WARN_ON(!np || !*np)) - return 0; - - return *np == data; -} - -/** - * devm_of_clk_del_provider() - Remove clock provider registered using devm - * @dev: Device to whose lifetime the clock provider was bound - */ -void devm_of_clk_del_provider(struct device *dev) -{ - int ret; - struct device_node *np = get_clk_provider_node(dev); - - ret = devres_release(dev, devm_of_clk_release_provider, - devm_clk_provider_match, np); - - WARN_ON(ret); -} -EXPORT_SYMBOL(devm_of_clk_del_provider); - /** * of_parse_clkspec() - Parse a DT clock specifier for a given device node * @np: device node to parse clock specifier from diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 1615010aa0ec..305e18eb23cf 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -1454,7 +1454,7 @@ int devm_of_clk_add_hw_provider(struct device *dev, void *data), void *data); void of_clk_del_provider(struct device_node *np); -void devm_of_clk_del_provider(struct device *dev); + struct clk *of_clk_src_simple_get(struct of_phandle_args *clkspec, void *data); struct clk_hw *of_clk_hw_simple_get(struct of_phandle_args *clkspec, @@ -1491,7 +1491,7 @@ static inline int devm_of_clk_add_hw_provider(struct device *dev, return 0; } static inline void of_clk_del_provider(struct device_node *np) {} -static inline void devm_of_clk_del_provider(struct device *dev) {} + static inline struct clk *of_clk_src_simple_get( struct of_phandle_args *clkspec, void *data) { -- cgit v1.2.3 From 07bdf48d3fee12268bf9a179821aee9b80f5239c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 23 Jun 2022 14:57:18 +0300 Subject: clkdev: Remove never used devm_clk_release_clkdev() For the entire history of the devm_clk_release_clkdev() existence (since 2018) it was never used. Remove it for good. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220623115719.52683-2-andriy.shevchenko@linux.intel.com Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 34 ---------------------------------- include/linux/clkdev.h | 2 -- 2 files changed, 36 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index a4d4bd3f5be5..a0fd90f07891 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -351,40 +351,6 @@ static void devm_clkdev_release(struct device *dev, void *res) clkdev_drop(*(struct clk_lookup **)res); } -static int devm_clk_match_clkdev(struct device *dev, void *res, void *data) -{ - struct clk_lookup **l = res; - - return *l == data; -} - -/** - * devm_clk_release_clkdev - Resource managed clkdev lookup release - * @dev: device this lookup is bound - * @con_id: connection ID string on device - * @dev_id: format string describing device name - * - * Drop the clkdev lookup created with devm_clk_hw_register_clkdev. - * Normally this function will not need to be called and the resource - * management code will ensure that the resource is freed. - */ -void devm_clk_release_clkdev(struct device *dev, const char *con_id, - const char *dev_id) -{ - struct clk_lookup *cl; - int rval; - - mutex_lock(&clocks_mutex); - cl = clk_find(dev_id, con_id); - mutex_unlock(&clocks_mutex); - - WARN_ON(!cl); - rval = devres_release(dev, devm_clkdev_release, - devm_clk_match_clkdev, cl); - WARN_ON(rval); -} -EXPORT_SYMBOL(devm_clk_release_clkdev); - /** * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw * @dev: device this lookup is bound diff --git a/include/linux/clkdev.h b/include/linux/clkdev.h index 8a8423eb8e9a..45570bc21a43 100644 --- a/include/linux/clkdev.h +++ b/include/linux/clkdev.h @@ -46,6 +46,4 @@ int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *); int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw, const char *con_id, const char *dev_id); -void devm_clk_release_clkdev(struct device *dev, const char *con_id, - const char *dev_id); #endif -- cgit v1.2.3 From d61876a2850faf0f07843ecf157a42a79e7e34a2 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 23 Jun 2022 14:57:19 +0300 Subject: clkdev: Simplify devm_clk_hw_register_clkdev() function Use devm_add_action_or_reset() instead of devres_alloc() and devres_add(), which works the same. This will simplify the code. There is no functional changes. Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20220623115719.52683-3-andriy.shevchenko@linux.intel.com Signed-off-by: Stephen Boyd --- drivers/clk/clkdev.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c index a0fd90f07891..ee37d0be6877 100644 --- a/drivers/clk/clkdev.c +++ b/drivers/clk/clkdev.c @@ -346,9 +346,9 @@ int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id, } EXPORT_SYMBOL(clk_hw_register_clkdev); -static void devm_clkdev_release(struct device *dev, void *res) +static void devm_clkdev_release(void *res) { - clkdev_drop(*(struct clk_lookup **)res); + clkdev_drop(res); } /** @@ -369,17 +369,13 @@ static void devm_clkdev_release(struct device *dev, void *res) int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw, const char *con_id, const char *dev_id) { - int rval = -ENOMEM; - struct clk_lookup **cl; - - cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL); - if (cl) { - rval = do_clk_register_clkdev(hw, cl, con_id, dev_id); - if (!rval) - devres_add(dev, cl); - else - devres_free(cl); - } - return rval; + struct clk_lookup *cl; + int rval; + + rval = do_clk_register_clkdev(hw, &cl, con_id, dev_id); + if (rval) + return rval; + + return devm_add_action_or_reset(dev, devm_clkdev_release, cl); } EXPORT_SYMBOL(devm_clk_hw_register_clkdev); -- cgit v1.2.3 From 058a3996b888ab60eb1857fb4fd28f1b89a9a95a Mon Sep 17 00:00:00 2001 From: Liang He Date: Thu, 15 Sep 2022 11:11:21 +0800 Subject: clk: ti: Balance of_node_get() calls for of_find_node_by_name() In ti_find_clock_provider(), of_find_node_by_name() will call of_node_put() for the 'from' argument, possibly putting the node one too many times. Let's maintain the of_node_get() from the previous search and only put when we're exiting the function early. This should avoid a misbalanced reference count on the node. Fixes: 51f661ef9a10 ("clk: ti: Add ti_find_clock_provider() to use clock-output-names") Signed-off-by: Liang He Link: https://lore.kernel.org/r/20220915031121.4003589-1-windhl@126.com [sboyd@kernel.org: Rewrite commit text, maintain reference instead of get again] Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/clk/ti/clk.c b/drivers/clk/ti/clk.c index ef2a445c63a3..a99279265e40 100644 --- a/drivers/clk/ti/clk.c +++ b/drivers/clk/ti/clk.c @@ -139,11 +139,12 @@ static struct device_node *ti_find_clock_provider(struct device_node *from, break; } } - of_node_put(from); kfree(tmp); - if (found) + if (found) { + of_node_put(from); return np; + } /* Fall back to using old node name base provider name */ return of_find_node_by_name(from, name); -- cgit v1.2.3 From 9c59a01caba26ec06fefd6ca1f22d5fd1de57d63 Mon Sep 17 00:00:00 2001 From: Miaoqian Lin Date: Thu, 2 Jun 2022 07:08:36 +0400 Subject: clk: ti: dra7-atl: Fix reference leak in of_dra7_atl_clk_probe pm_runtime_get_sync() will increment pm usage counter. Forgetting to putting operation will result in reference leak. Add missing pm_runtime_put_sync in some error paths. Fixes: 9ac33b0ce81f ("CLK: TI: Driver for DRA7 ATL (Audio Tracking Logic)") Signed-off-by: Miaoqian Lin Link: https://lore.kernel.org/r/20220602030838.52057-1-linmq006@gmail.com Reviewed-by: Tony Lindgren Signed-off-by: Stephen Boyd --- drivers/clk/ti/clk-dra7-atl.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index f0f5bf68b6d2..ff4d6a951681 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -245,14 +245,16 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) if (rc) { pr_err("%s: failed to lookup atl clock %d\n", __func__, i); - return -EINVAL; + ret = -EINVAL; + goto pm_put; } clk = of_clk_get_from_provider(&clkspec); if (IS_ERR(clk)) { pr_err("%s: failed to get atl clock %d from provider\n", __func__, i); - return PTR_ERR(clk); + ret = PTR_ERR(clk); + goto pm_put; } cdesc = to_atl_desc(__clk_get_hw(clk)); @@ -285,8 +287,9 @@ static int of_dra7_atl_clk_probe(struct platform_device *pdev) if (cdesc->enabled) atl_clk_enable(__clk_get_hw(clk)); } - pm_runtime_put_sync(cinfo->dev); +pm_put: + pm_runtime_put_sync(cinfo->dev); return ret; } -- cgit v1.2.3 From f816ac1115b9d4f874efa04f721eba99cf69067e Mon Sep 17 00:00:00 2001 From: ye xingchen Date: Tue, 6 Sep 2022 07:23:22 +0000 Subject: clk: mvebu: armada-37xx-tbg: Remove the unneeded result variable Return the value of_clk_add_hw_provider() directly instead of storing it in another redundant variable. Reported-by: Zeal Robot Signed-off-by: ye xingchen Link: https://lore.kernel.org/r/20220906072322.337253-1-ye.xingchen@zte.com.cn Signed-off-by: Stephen Boyd --- drivers/clk/mvebu/armada-37xx-tbg.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/clk/mvebu/armada-37xx-tbg.c b/drivers/clk/mvebu/armada-37xx-tbg.c index 585a02e0b330..fc403ad735ad 100644 --- a/drivers/clk/mvebu/armada-37xx-tbg.c +++ b/drivers/clk/mvebu/armada-37xx-tbg.c @@ -87,7 +87,7 @@ static int armada_3700_tbg_clock_probe(struct platform_device *pdev) struct resource *res; struct clk *parent; void __iomem *reg; - int i, ret; + int i; hw_tbg_data = devm_kzalloc(&pdev->dev, struct_size(hw_tbg_data, hws, NUM_TBG), @@ -123,9 +123,7 @@ static int armada_3700_tbg_clock_probe(struct platform_device *pdev) dev_err(dev, "Can't register TBG clock %s\n", name); } - ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, hw_tbg_data); - - return ret; + return of_clk_add_hw_provider(np, of_clk_hw_onecell_get, hw_tbg_data); } static int armada_3700_tbg_clock_remove(struct platform_device *pdev) -- cgit v1.2.3 From 7942ac9fe9c30804fc9403a6e1fae4b8ad50181d Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 21 May 2022 13:10:52 +0200 Subject: clk: nxp: fix typo in comment Spelling mistake (triple letters) in comment. Detected with the help of Coccinelle. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20220521111145.81697-42-Julia.Lawall@inria.fr Acked-by: Vladimir Zapolskiy Signed-off-by: Stephen Boyd --- drivers/clk/nxp/clk-lpc18xx-cgu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/nxp/clk-lpc18xx-cgu.c b/drivers/clk/nxp/clk-lpc18xx-cgu.c index f253ef1996b1..69ebf65081b8 100644 --- a/drivers/clk/nxp/clk-lpc18xx-cgu.c +++ b/drivers/clk/nxp/clk-lpc18xx-cgu.c @@ -606,7 +606,7 @@ static void __init lpc18xx_cgu_register_source_clks(struct device_node *np, if (IS_ERR(clk)) pr_warn("%s: failed to register irc clk\n", __func__); - /* Register crystal oscillator controlller */ + /* Register crystal oscillator controller */ parents[0] = of_clk_get_parent_name(np, 0); clk = clk_register_gate(NULL, clk_src_names[CLK_SRC_OSC], parents[0], 0, base + LPC18XX_CGU_XTAL_OSC_CTRL, -- cgit v1.2.3 From fd30ac84f3022ea3c8c6380dfb919c869c6fd9e2 Mon Sep 17 00:00:00 2001 From: Yang Yingliang Date: Tue, 13 Sep 2022 11:14:42 +0800 Subject: clk: clocking-wizard: Use dev_err_probe() helper dev_err() can be replace with dev_err_probe() which will check if error code is -EPROBE_DEFER. Signed-off-by: Yang Yingliang Link: https://lore.kernel.org/r/20220913031442.980720-1-yangyingliang@huawei.com Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/clk-xlnx-clock-wizard.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c index 5b8433468cc5..eb1dfe7ecc1b 100644 --- a/drivers/clk/xilinx/clk-xlnx-clock-wizard.c +++ b/drivers/clk/xilinx/clk-xlnx-clock-wizard.c @@ -448,18 +448,14 @@ static int clk_wzrd_probe(struct platform_device *pdev) } clk_wzrd->clk_in1 = devm_clk_get(&pdev->dev, "clk_in1"); - if (IS_ERR(clk_wzrd->clk_in1)) { - if (clk_wzrd->clk_in1 != ERR_PTR(-EPROBE_DEFER)) - dev_err(&pdev->dev, "clk_in1 not found\n"); - return PTR_ERR(clk_wzrd->clk_in1); - } + if (IS_ERR(clk_wzrd->clk_in1)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->clk_in1), + "clk_in1 not found\n"); clk_wzrd->axi_clk = devm_clk_get(&pdev->dev, "s_axi_aclk"); - if (IS_ERR(clk_wzrd->axi_clk)) { - if (clk_wzrd->axi_clk != ERR_PTR(-EPROBE_DEFER)) - dev_err(&pdev->dev, "s_axi_aclk not found\n"); - return PTR_ERR(clk_wzrd->axi_clk); - } + if (IS_ERR(clk_wzrd->axi_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(clk_wzrd->axi_clk), + "s_axi_aclk not found\n"); ret = clk_prepare_enable(clk_wzrd->axi_clk); if (ret) { dev_err(&pdev->dev, "enabling s_axi_aclk failed\n"); -- cgit v1.2.3 From c00b5f204041581fadcc6d3de7f9407d2d110035 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Mon, 3 Oct 2022 13:26:08 -0700 Subject: clk: clocking-wizard: Depend on HAS_IOMEM This driver uses devm_platform_ioremap_resource() and thus depends on HAS_IOMEM. Add the Kconfig dependency to avoid build issues. Reported-by: kernel test robot Cc: Shubhrajyoti Datta Fixes: c822490f52da ("clk: clocking-wizard: Move clocking-wizard out") Link: https://lore.kernel.org/r/20221003202608.2611295-1-sboyd@kernel.org Signed-off-by: Stephen Boyd --- drivers/clk/xilinx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/xilinx/Kconfig b/drivers/clk/xilinx/Kconfig index 5b99ecfd2f06..f205522c40ff 100644 --- a/drivers/clk/xilinx/Kconfig +++ b/drivers/clk/xilinx/Kconfig @@ -20,6 +20,7 @@ config XILINX_VCU config COMMON_CLK_XLNX_CLKWZRD tristate "Xilinx Clocking Wizard" depends on COMMON_CLK && OF + depends on HAS_IOMEM help Support for the Xilinx Clocking Wizard IP core clock generator. Adds support for clocking wizard and compatible. -- cgit v1.2.3 From ae039f0fc0432922e95888cb470e5d9e1d8f6934 Mon Sep 17 00:00:00 2001 From: Yihao Han Date: Fri, 8 Apr 2022 06:06:09 -0700 Subject: clk: clk-xgene: simplify if-if to if-else Replace `if (!pclk->param.csr_reg)` with `else` for simplification and add curly brackets according to the kernel coding style: "Do not unnecessarily use braces where a single statement will do." ... "This does not apply if only one branch of a conditional statement is a single statement; in the latter case use braces in both branches" Please refer to: https://www.kernel.org/doc/html/v5.17-rc8/process/coding-style.html Signed-off-by: Yihao Han Link: https://lore.kernel.org/r/20220408130617.14963-1-hanyihao@vivo.com Signed-off-by: Stephen Boyd --- drivers/clk/clk-xgene.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/clk-xgene.c b/drivers/clk/clk-xgene.c index 857217cbcef8..0c3d0cee98c8 100644 --- a/drivers/clk/clk-xgene.c +++ b/drivers/clk/clk-xgene.c @@ -522,10 +522,10 @@ static int xgene_clk_is_enabled(struct clk_hw *hw) pr_debug("%s clock is %s\n", clk_hw_get_name(hw), data & pclk->param.reg_clk_mask ? "enabled" : "disabled"); + } else { + return 1; } - if (!pclk->param.csr_reg) - return 1; return data & pclk->param.reg_clk_mask ? 1 : 0; } -- cgit v1.2.3 From 8a977bbb17e2619ba06559f102cffd8678c3084e Mon Sep 17 00:00:00 2001 From: Clément Léger Date: Fri, 17 Jun 2022 12:33:06 +0200 Subject: clk: allow building lan966x as a module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set the COMMON_CLK_LAN966X option as a tristate and switch from builtin_platform_driver() to module_platform_driver() to allow building and using this driver as a module. Signed-off-by: Clément Léger Link: https://lore.kernel.org/r/20220617103306.489466-1-clement.leger@bootlin.com Signed-off-by: Stephen Boyd --- drivers/clk/Kconfig | 2 +- drivers/clk/clk-lan966x.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 48f8f4221e21..ac77d4b2c742 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -249,7 +249,7 @@ config COMMON_CLK_GEMINI platform, also known as SL3516 or CS3516. config COMMON_CLK_LAN966X - bool "Generic Clock Controller driver for LAN966X SoC" + tristate "Generic Clock Controller driver for LAN966X SoC" depends on HAS_IOMEM depends on OF depends on SOC_LAN966 || COMPILE_TEST diff --git a/drivers/clk/clk-lan966x.c b/drivers/clk/clk-lan966x.c index 81cb90955d68..460e7216bfa1 100644 --- a/drivers/clk/clk-lan966x.c +++ b/drivers/clk/clk-lan966x.c @@ -286,7 +286,7 @@ static struct platform_driver lan966x_clk_driver = { .of_match_table = lan966x_clk_dt_ids, }, }; -builtin_platform_driver(lan966x_clk_driver); +module_platform_driver(lan966x_clk_driver); MODULE_AUTHOR("Kavyasree Kotagiri "); MODULE_DESCRIPTION("LAN966X clock driver"); -- cgit v1.2.3