2023-07-31 13:03:28

by David Yang

[permalink] [raw]
Subject: [PATCH v6 00/13] clk: hisilicon: Migrate devm APIs

Migrate devm APIs for HiSilicon clock drivers and remove redundant codes.

This series is a partial improvement of [1]

v2: fix test robot error
v3:
* size_t for all these num types
* hisi_clk_unregister() change into separate patch
* keep relevant header inclusions
* split driver files changes into separate patches
* explain hisi_clk_register_fn() checkpatch warnings
* not fixed: MODULE_LICENSE("GPL v2"), as stated in SPDX-License-Identifier
* not fixed: "hisilicon,hip04-clock" un-documented, as none of dts files in
arch/ use it, better to ask hisi people why they pushed this driver
v4:
* typo: hisi_clocks_get_nr() should check clks->nr first
* unexport hisi_clk_unregister_fn() as no one use them outside
v5: catch up with remove_new refactoring
v6: fix compilation error and expand macros

Links:
[1]: https://lore.kernel.org/r/[email protected]
v1: https://lore.kernel.org/r/[email protected]
v2: https://lore.kernel.org/r/[email protected]
v3: https://lore.kernel.org/r/[email protected]
v4: https://lore.kernel.org/r/[email protected]
v5: https://lore.kernel.org/r/[email protected]

David Yang (13):
clk: hisilicon: Add helper functions for platform driver
clk: hisilicon: hi3516cv300: Use helper functions
clk: hisilicon: hi3798cv200: Use helper functions
clk: hisilicon: Remove hisi_crg_funcs
clk: hisilicon: hi3519: Use helper functions
clk: hisilicon: hi3559a: Use helper functions
clk: hisilicon: hi3660: Convert into module
clk: hisilicon: hi3670: Convert into module
clk: hisilicon: hi3620: Convert into platform driver module
clk: hisilicon: hi6220: Convert into platform driver module
clk: hisilicon: hip04: Convert into platform driver module
clk: hisilicon: hix5hd2: Convert into platform driver module
clk: hisilicon: Migrate devm APIs

drivers/clk/hisilicon/clk-hi3519.c | 127 +-----
drivers/clk/hisilicon/clk-hi3559a.c | 253 +++--------
drivers/clk/hisilicon/clk-hi3620.c | 212 +++++-----
drivers/clk/hisilicon/clk-hi3660.c | 192 +++------
drivers/clk/hisilicon/clk-hi3670.c | 248 ++++-------
drivers/clk/hisilicon/clk-hi6220-stub.c | 9 +-
drivers/clk/hisilicon/clk-hi6220.c | 229 +++++-----
drivers/clk/hisilicon/clk-hip04.c | 39 +-
drivers/clk/hisilicon/clk-hisi-phase.c | 13 +-
drivers/clk/hisilicon/clk-hix5hd2.c | 98 +++--
drivers/clk/hisilicon/clk.c | 490 +++++++++++++---------
drivers/clk/hisilicon/clk.h | 141 ++++---
drivers/clk/hisilicon/clkdivider-hi6220.c | 24 +-
drivers/clk/hisilicon/clkgate-separated.c | 26 +-
drivers/clk/hisilicon/crg-hi3516cv300.c | 171 +-------
drivers/clk/hisilicon/crg-hi3798cv200.c | 196 +--------
drivers/clk/hisilicon/crg.h | 11 +-
drivers/clk/hisilicon/reset.c | 42 ++
18 files changed, 998 insertions(+), 1523 deletions(-)


base-commit: 5d0c230f1de8c7515b6567d9afba1f196fb4e2f4
--
2.40.1



2023-07-31 13:04:29

by David Yang

[permalink] [raw]
Subject: [PATCH v6 07/13] clk: hisilicon: hi3660: Convert into module

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk-hi3660.c | 192 ++++++++---------------------
1 file changed, 53 insertions(+), 139 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hi3660.c b/drivers/clk/hisilicon/clk-hi3660.c
index 41f61726ab19..9ece1d57cbe6 100644
--- a/drivers/clk/hisilicon/clk-hi3660.c
+++ b/drivers/clk/hisilicon/clk-hi3660.c
@@ -5,9 +5,13 @@
*/

#include <dt-bindings/clock/hi3660-clock.h>
+
#include <linux/clk-provider.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
+
#include "clk.h"

static const struct hisi_fixed_rate_clock hi3660_fixed_rate_clks[] = {
@@ -469,169 +473,79 @@ static const struct hisi_gate_clock hi3660_iomcu_gate_sep_clks[] = {
CLK_SET_RATE_PARENT, 0x90, 0, 0, },
};

-static struct hisi_clock_data *clk_crgctrl_data;
-
-static void hi3660_clk_iomcu_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_iomcu_gate_sep_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate_sep(hi3660_iomcu_gate_sep_clks,
- ARRAY_SIZE(hi3660_iomcu_gate_sep_clks),
- clk_data);
-}
-
-static void hi3660_clk_pmuctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_pmu_gate_clks);
-
- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
-
- hisi_clk_register_gate(hi3660_pmu_gate_clks,
- ARRAY_SIZE(hi3660_pmu_gate_clks), clk_data);
-}
+static const struct hisi_clocks hi3660_clk_iomcu_clks = {
+ .gate_sep_clks = hi3660_iomcu_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_iomcu_gate_sep_clks),
+};

-static void hi3660_clk_pctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_pctrl_gate_clks);
+static const struct hisi_clocks hi3660_clk_pmuctrl_clks = {
+ .gate_clks = hi3660_pmu_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_pmu_gate_clks),
+};

- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
- hisi_clk_register_gate(hi3660_pctrl_gate_clks,
- ARRAY_SIZE(hi3660_pctrl_gate_clks), clk_data);
-}
+static const struct hisi_clocks hi3660_clk_pctrl_clks = {
+ .gate_clks = hi3660_pctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_pctrl_gate_clks),
+};

-static void hi3660_clk_sctrl_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
- int nr = ARRAY_SIZE(hi3660_sctrl_gate_clks) +
- ARRAY_SIZE(hi3660_sctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3660_sctrl_mux_clks) +
- ARRAY_SIZE(hi3660_sctrl_divider_clks);
+static const struct hisi_clocks hi3660_clk_sctrl_clks = {
+ .mux_clks = hi3660_sctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3660_sctrl_mux_clks),
+ .divider_clks = hi3660_sctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3660_sctrl_divider_clks),
+ .gate_clks = hi3660_sctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_sctrl_gate_clks),
+ .gate_sep_clks = hi3660_sctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_sctrl_gate_sep_clks),
+};

- clk_data = hisi_clk_init(np, nr);
- if (!clk_data)
- return;
- hisi_clk_register_gate(hi3660_sctrl_gate_clks,
- ARRAY_SIZE(hi3660_sctrl_gate_clks), clk_data);
- hisi_clk_register_gate_sep(hi3660_sctrl_gate_sep_clks,
- ARRAY_SIZE(hi3660_sctrl_gate_sep_clks),
- clk_data);
- hisi_clk_register_mux(hi3660_sctrl_mux_clks,
- ARRAY_SIZE(hi3660_sctrl_mux_clks), clk_data);
- hisi_clk_register_divider(hi3660_sctrl_divider_clks,
- ARRAY_SIZE(hi3660_sctrl_divider_clks),
- clk_data);
-}
+static const struct hisi_clocks hi3660_clk_crgctrl_clks = {
+ .fixed_rate_clks = hi3660_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3660_fixed_rate_clks),
+ .fixed_factor_clks = hi3660_crg_fixed_factor_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
+ .mux_clks = hi3660_crgctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3660_crgctrl_mux_clks),
+ .divider_clks = hi3660_crgctrl_divider_clks,
+ .divider_clks_num = ARRAY_SIZE(hi3660_crgctrl_divider_clks),
+ .gate_clks = hi3660_crgctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3660_crgctrl_gate_clks),
+ .gate_sep_clks = hi3660_crgctrl_gate_sep_clks,
+ .gate_sep_clks_num = ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
+};

static void hi3660_clk_crgctrl_early_init(struct device_node *np)
{
- int nr = ARRAY_SIZE(hi3660_fixed_rate_clks) +
- ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks) +
- ARRAY_SIZE(hi3660_crgctrl_gate_clks) +
- ARRAY_SIZE(hi3660_crgctrl_mux_clks) +
- ARRAY_SIZE(hi3660_crg_fixed_factor_clks) +
- ARRAY_SIZE(hi3660_crgctrl_divider_clks);
- int i;
-
- clk_crgctrl_data = hisi_clk_init(np, nr);
- if (!clk_crgctrl_data)
- return;
-
- for (i = 0; i < nr; i++)
- clk_crgctrl_data->clk_data.clks[i] = ERR_PTR(-EPROBE_DEFER);
-
- hisi_clk_register_fixed_rate(hi3660_fixed_rate_clks,
- ARRAY_SIZE(hi3660_fixed_rate_clks),
- clk_crgctrl_data);
+ hisi_clk_early_init(np, &hi3660_clk_crgctrl_clks);
}
CLK_OF_DECLARE_DRIVER(hi3660_clk_crgctrl, "hisilicon,hi3660-crgctrl",
hi3660_clk_crgctrl_early_init);

-static void hi3660_clk_crgctrl_init(struct device_node *np)
-{
- struct clk **clks;
- int i;
-
- if (!clk_crgctrl_data)
- hi3660_clk_crgctrl_early_init(np);
-
- /* clk_crgctrl_data initialization failed */
- if (!clk_crgctrl_data)
- return;
-
- hisi_clk_register_gate_sep(hi3660_crgctrl_gate_sep_clks,
- ARRAY_SIZE(hi3660_crgctrl_gate_sep_clks),
- clk_crgctrl_data);
- hisi_clk_register_gate(hi3660_crgctrl_gate_clks,
- ARRAY_SIZE(hi3660_crgctrl_gate_clks),
- clk_crgctrl_data);
- hisi_clk_register_mux(hi3660_crgctrl_mux_clks,
- ARRAY_SIZE(hi3660_crgctrl_mux_clks),
- clk_crgctrl_data);
- hisi_clk_register_fixed_factor(hi3660_crg_fixed_factor_clks,
- ARRAY_SIZE(hi3660_crg_fixed_factor_clks),
- clk_crgctrl_data);
- hisi_clk_register_divider(hi3660_crgctrl_divider_clks,
- ARRAY_SIZE(hi3660_crgctrl_divider_clks),
- clk_crgctrl_data);
-
- clks = clk_crgctrl_data->clk_data.clks;
- for (i = 0; i < clk_crgctrl_data->clk_data.clk_num; i++) {
- if (IS_ERR(clks[i]) && PTR_ERR(clks[i]) != -EPROBE_DEFER)
- pr_err("Failed to register crgctrl clock[%d] err=%ld\n",
- i, PTR_ERR(clks[i]));
- }
-}
-
static const struct of_device_id hi3660_clk_match_table[] = {
{ .compatible = "hisilicon,hi3660-crgctrl",
- .data = hi3660_clk_crgctrl_init },
+ .data = &hi3660_clk_crgctrl_clks },
{ .compatible = "hisilicon,hi3660-pctrl",
- .data = hi3660_clk_pctrl_init },
+ .data = &hi3660_clk_pctrl_clks },
{ .compatible = "hisilicon,hi3660-pmuctrl",
- .data = hi3660_clk_pmuctrl_init },
+ .data = &hi3660_clk_pmuctrl_clks },
{ .compatible = "hisilicon,hi3660-sctrl",
- .data = hi3660_clk_sctrl_init },
+ .data = &hi3660_clk_sctrl_clks },
{ .compatible = "hisilicon,hi3660-iomcu",
- .data = hi3660_clk_iomcu_init },
+ .data = &hi3660_clk_iomcu_clks },
{ }
};
-
-static int hi3660_clk_probe(struct platform_device *pdev)
-{
- struct device *dev = &pdev->dev;
- struct device_node *np = pdev->dev.of_node;
- void (*init_func)(struct device_node *np);
-
- init_func = of_device_get_match_data(dev);
- if (!init_func)
- return -ENODEV;
-
- init_func(np);
-
- return 0;
-}
+MODULE_DEVICE_TABLE(of, hi3660_clk_match_table);

static struct platform_driver hi3660_clk_driver = {
- .probe = hi3660_clk_probe,
+ .probe = hisi_clk_probe,
+ .remove_new = hisi_clk_remove,
.driver = {
.name = "hi3660-clk",
.of_match_table = hi3660_clk_match_table,
},
};

-static int __init hi3660_clk_init(void)
-{
- return platform_driver_register(&hi3660_clk_driver);
-}
-core_initcall(hi3660_clk_init);
+module_platform_driver(hi3660_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hi3660 Clock Driver");
--
2.40.1


2023-07-31 13:20:01

by David Yang

[permalink] [raw]
Subject: [PATCH v6 13/13] clk: hisilicon: Migrate devm APIs

Migrates devm APIs for HiSilicon clock drivers.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk-hi3559a.c | 29 +-
drivers/clk/hisilicon/clk-hi3620.c | 29 +-
drivers/clk/hisilicon/clk-hi6220-stub.c | 9 +-
drivers/clk/hisilicon/clk-hi6220.c | 4 +-
drivers/clk/hisilicon/clk-hisi-phase.c | 13 +-
drivers/clk/hisilicon/clk-hix5hd2.c | 15 +-
drivers/clk/hisilicon/clk.c | 413 ++++++++++------------
drivers/clk/hisilicon/clk.h | 99 +++---
drivers/clk/hisilicon/clkdivider-hi6220.c | 24 +-
drivers/clk/hisilicon/clkgate-separated.c | 26 +-
10 files changed, 301 insertions(+), 360 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hi3559a.c b/drivers/clk/hisilicon/clk-hi3559a.c
index 83a46b432ca9..c5916d219963 100644
--- a/drivers/clk/hisilicon/clk-hi3559a.c
+++ b/drivers/clk/hisilicon/clk-hi3559a.c
@@ -458,17 +458,16 @@ hisi_clk_register_pll(struct device *dev, const void *clocks,
{
const struct hi3559av100_pll_clock *clks = clocks;
void __iomem *base = data->base;
- struct hi3559av100_clk_pll *p_clk = NULL;
- struct clk *clk = NULL;
+ struct hi3559av100_clk_pll *p_clk;
struct clk_init_data init;
int i;
-
- p_clk = devm_kzalloc(dev, sizeof(*p_clk) * num, GFP_KERNEL);
-
- if (!p_clk)
- return -ENOMEM;
+ int ret;

for (i = 0; i < num; i++) {
+ p_clk = devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL);
+ if (!p_clk)
+ return -ENOMEM;
+
init.name = clks[i].name;
init.flags = 0;
init.parent_names =
@@ -491,16 +490,14 @@ hisi_clk_register_pll(struct device *dev, const void *clocks,
p_clk->refdiv_width = clks[i].refdiv_width;
p_clk->hw.init = &init;

- clk = clk_register(NULL, &p_clk->hw);
- if (IS_ERR(clk)) {
- devm_kfree(dev, p_clk);
+ ret = devm_clk_hw_register(dev, &p_clk->hw);
+ if (ret) {
dev_err(dev, "%s: failed to register clock %s\n",
- __func__, clks[i].name);
- return PTR_ERR(clk);
+ __func__, clks[i].name);
+ return ret;
}

- data->clk_data.clks[clks[i].id] = clk;
- p_clk++;
+ data->clk_data->hws[clks[i].id] = &p_clk->hw;
}

return 0;
@@ -629,7 +626,7 @@ static int hi3559av100_shub_default_clk_set(struct device *dev, struct hisi_cloc
void __iomem *crg_base;
unsigned int val;

- crg_base = ioremap(CRG_BASE_ADDR, SZ_4K);
+ crg_base = devm_ioremap(dev, CRG_BASE_ADDR, SZ_4K);

/* SSP: 192M/2 */
val = readl_relaxed(crg_base + 0x20);
@@ -641,7 +638,7 @@ static int hi3559av100_shub_default_clk_set(struct device *dev, struct hisi_cloc
val |= (0x1 << 28);
writel_relaxed(val, crg_base + 0x1C);

- iounmap(crg_base);
+ devm_iounmap(dev, crg_base);
crg_base = NULL;

return 0;
diff --git a/drivers/clk/hisilicon/clk-hi3620.c b/drivers/clk/hisilicon/clk-hi3620.c
index a08778de8dc2..b831bb90a61a 100644
--- a/drivers/clk/hisilicon/clk-hi3620.c
+++ b/drivers/clk/hisilicon/clk-hi3620.c
@@ -11,12 +11,10 @@

#include <linux/kernel.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/io.h>
#include <linux/module.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
#include <linux/of_device.h>
-#include <linux/slab.h>

#include <dt-bindings/clock/hi3620-clock.h>

@@ -399,15 +397,15 @@ static const struct clk_ops clk_mmc_ops = {
.recalc_rate = mmc_clk_recalc_rate,
};

-static struct clk *
+static struct clk_hw *
clk_register_hisi_mmc(struct device *dev, const struct hisi_mmc_clock *mmc_clk,
void __iomem *base)
{
struct clk_mmc *mclk;
- struct clk *clk;
struct clk_init_data init;
+ int ret;

- mclk = kzalloc(sizeof(*mclk), GFP_KERNEL);
+ mclk = devm_kzalloc(dev, sizeof(*mclk), GFP_KERNEL);
if (!mclk)
return ERR_PTR(-ENOMEM);

@@ -431,26 +429,31 @@ clk_register_hisi_mmc(struct device *dev, const struct hisi_mmc_clock *mmc_clk,
mclk->sam_off = mmc_clk->sam_off;
mclk->sam_bits = mmc_clk->sam_bits;

- clk = clk_register(NULL, &mclk->hw);
- if (WARN_ON(IS_ERR(clk)))
- kfree(mclk);
- return clk;
+ ret = devm_clk_hw_register(dev, &mclk->hw);
+ if (ret) {
+ dev_err(dev, "%s: failed to register clock %s\n",
+ __func__, init.name);
+ return ERR_PTR(ret);
+ }
+
+ return &mclk->hw;
}

static int hisi_register_clk_mmc(struct device *dev, const void *clocks,
size_t num, struct hisi_clock_data *data)
{
const struct hisi_mmc_clock *clks = clocks;
+ int i;

- for (int i = 0; i < num; i++) {
- struct clk *clk = clk_register_hisi_mmc(dev, &clks[i], data->base);
+ for (i = 0; i < num; i++) {
+ struct clk_hw *clk = clk_register_hisi_mmc(dev, &clks[i], data->base);

if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
return PTR_ERR(clk);
}
- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[clks[i].id] = clk;
}

return 0;
diff --git a/drivers/clk/hisilicon/clk-hi6220-stub.c b/drivers/clk/hisilicon/clk-hi6220-stub.c
index 4fdee4424d82..dd996a43958e 100644
--- a/drivers/clk/hisilicon/clk-hi6220-stub.c
+++ b/drivers/clk/hisilicon/clk-hi6220-stub.c
@@ -195,7 +195,6 @@ static int hi6220_stub_clk_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct clk_init_data init;
struct hi6220_stub_clk *stub_clk;
- struct clk *clk;
struct device_node *np = pdev->dev.of_node;
int ret;

@@ -233,11 +232,11 @@ static int hi6220_stub_clk_probe(struct platform_device *pdev)
init.num_parents = 0;
init.flags = 0;

- clk = devm_clk_register(dev, &stub_clk->hw);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
+ ret = devm_clk_hw_register(dev, &stub_clk->hw);
+ if (ret)
+ return ret;

- ret = of_clk_add_provider(np, of_clk_src_simple_get, clk);
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &stub_clk->hw);
if (ret) {
dev_err(dev, "failed to register OF clock provider\n");
return ret;
diff --git a/drivers/clk/hisilicon/clk-hi6220.c b/drivers/clk/hisilicon/clk-hi6220.c
index 6eac73408745..50ae5df4070b 100644
--- a/drivers/clk/hisilicon/clk-hi6220.c
+++ b/drivers/clk/hisilicon/clk-hi6220.c
@@ -20,9 +20,7 @@ static int
hi6220_clk_register_divider_stub(struct device *dev, const void *clks,
size_t num, struct hisi_clock_data *data)
{
- /* INCOMPLETE PATCH */
- hi6220_clk_register_divider(clks, num, data);
- return 0;
+ return hi6220_clk_register_divider(dev, clks, num, data);
}

/* clocks in AO (always on) controller */
diff --git a/drivers/clk/hisilicon/clk-hisi-phase.c b/drivers/clk/hisilicon/clk-hisi-phase.c
index ba6afad66a2b..15a23dd6edb1 100644
--- a/drivers/clk/hisilicon/clk-hisi-phase.c
+++ b/drivers/clk/hisilicon/clk-hisi-phase.c
@@ -5,11 +5,11 @@
* Simple HiSilicon phase clock implementation.
*/

+#include <linux/device.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>

#include "clk.h"

@@ -90,12 +90,13 @@ static const struct clk_ops clk_phase_ops = {
.set_phase = hisi_clk_set_phase,
};

-struct clk *clk_register_hisi_phase(struct device *dev,
+struct clk_hw *devm_clk_hw_register_hisi_phase(struct device *dev,
const struct hisi_phase_clock *clks,
void __iomem *base, spinlock_t *lock)
{
struct clk_hisi_phase *phase;
struct clk_init_data init;
+ int ret;

phase = devm_kzalloc(dev, sizeof(struct clk_hisi_phase), GFP_KERNEL);
if (!phase)
@@ -116,6 +117,10 @@ struct clk *clk_register_hisi_phase(struct device *dev,
phase->phase_num = clks->phase_num;
phase->hw.init = &init;

- return devm_clk_register(dev, &phase->hw);
+ ret = devm_clk_hw_register(dev, &phase->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &phase->hw;
}
-EXPORT_SYMBOL_GPL(clk_register_hisi_phase);
+EXPORT_SYMBOL_GPL(devm_clk_hw_register_hisi_phase);
diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index 6f988a7574b4..8bf9692affce 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -6,7 +6,7 @@

#include <dt-bindings/clock/hix5hd2-clock.h>

-#include <linux/slab.h>
+#include <linux/device.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/module.h>
@@ -260,13 +260,13 @@ hix5hd2_clk_register_complex(struct device *dev, const void *clocks, size_t num,
const struct hix5hd2_complex_clock *clks = clocks;
void __iomem *base = data->base;
int i;
+ int ret;

for (i = 0; i < num; i++) {
struct hix5hd2_clk_complex *p_clk;
- struct clk *clk;
struct clk_init_data init;

- p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
+ p_clk = devm_kzalloc(dev, sizeof(*p_clk), GFP_KERNEL);
if (!p_clk)
return -ENOMEM;

@@ -289,15 +289,14 @@ hix5hd2_clk_register_complex(struct device *dev, const void *clocks, size_t num,
p_clk->phy_rst_mask = clks[i].phy_rst_mask;
p_clk->hw.init = &init;

- clk = clk_register(NULL, &p_clk->hw);
- if (IS_ERR(clk)) {
- kfree(p_clk);
+ ret = devm_clk_hw_register(dev, &p_clk->hw);
+ if (ret) {
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
- return PTR_ERR(p_clk);
+ return ret;
}

- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[clks[i].id] = &p_clk->hw;
}

return 0;
diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index aa8908714cd0..4e150576e9eb 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -4,6 +4,7 @@
*
* Copyright (c) 2012-2013 Hisilicon Limited.
* Copyright (c) 2012-2013 Linaro Limited.
+ * Copyright (c) 2023 David Yang
*
* Author: Haojian Zhuang <[email protected]>
* Xin Li <[email protected]>
@@ -13,6 +14,8 @@
#include <linux/clkdev.h>
#include <linux/clk-provider.h>
#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/errno.h>
#include <linux/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -23,343 +26,301 @@

static DEFINE_SPINLOCK(hisi_clk_lock);

-struct hisi_clock_data *hisi_clk_alloc(struct platform_device *pdev,
- int nr_clks)
+struct hisi_clock_data *hisi_clk_init(struct device_node *np, size_t nr)
{
- struct hisi_clock_data *clk_data;
- struct resource *res;
- struct clk **clk_table;
-
- clk_data = devm_kmalloc(&pdev->dev, sizeof(*clk_data), GFP_KERNEL);
- if (!clk_data)
- return NULL;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return NULL;
- clk_data->base = devm_ioremap(&pdev->dev,
- res->start, resource_size(res));
- if (!clk_data->base)
- return NULL;
-
- clk_table = devm_kmalloc_array(&pdev->dev, nr_clks,
- sizeof(*clk_table),
- GFP_KERNEL);
- if (!clk_table)
- return NULL;
-
- clk_data->clk_data.clks = clk_table;
- clk_data->clk_data.clk_num = nr_clks;
-
- return clk_data;
-}
-EXPORT_SYMBOL_GPL(hisi_clk_alloc);
-
-struct hisi_clock_data *hisi_clk_init(struct device_node *np,
- int nr_clks)
-{
- struct hisi_clock_data *clk_data;
- struct clk **clk_table;
void __iomem *base;
+ struct hisi_clock_data *data;
+ int ret;
+ int i;

base = of_iomap(np, 0);
if (!base) {
pr_err("%s: failed to map clock registers\n", __func__);
- goto err;
+ return NULL;
}

- clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
- if (!clk_data)
- goto err;
+ data = kmalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return NULL;

- clk_data->base = base;
- clk_table = kcalloc(nr_clks, sizeof(*clk_table), GFP_KERNEL);
- if (!clk_table)
+ data->clk_data = kzalloc(sizeof(*data->clk_data) + nr * sizeof(data->clk_data->hws[0]),
+ GFP_KERNEL);
+ if (!data->clk_data)
goto err_data;

- clk_data->clk_data.clks = clk_table;
- clk_data->clk_data.clk_num = nr_clks;
- of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data->clk_data);
- return clk_data;
+ ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, data->clk_data);
+ if (ret)
+ goto err_clk;
+
+ data->base = base;
+ data->clks = NULL;
+ data->clk_data->num = nr;
+ for (i = 0; i < nr; i++)
+ data->clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);
+
+ return data;
+
+err_clk:
+ kfree(data->clk_data);
err_data:
- kfree(clk_data);
-err:
+ kfree(data);
return NULL;
}
EXPORT_SYMBOL_GPL(hisi_clk_init);

+#define hisi_clk_unregister_fn(type) \
+static void hisi_clk_unregister_##type(struct hisi_clock_data *data) \
+{ \
+ for (int i = 0; i < data->clks->type##_clks_num; i++) { \
+ struct clk_hw *clk = data->clk_data->hws[data->clks->type##_clks[i].id]; \
+\
+ if (clk && !IS_ERR(clk)) \
+ clk_hw_unregister_##type(clk); \
+ } \
+}
+
+hisi_clk_unregister_fn(fixed_rate)
+hisi_clk_unregister_fn(fixed_factor)
+
void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data)
{
if (data->clks) {
if (data->clks->fixed_rate_clks_num)
- hisi_clk_unregister_fixed_rate(data->clks->fixed_rate_clks,
- data->clks->fixed_rate_clks_num,
- data);
+ hisi_clk_unregister_fixed_rate(data);
if (data->clks->fixed_factor_clks_num)
- hisi_clk_unregister_fixed_factor(data->clks->fixed_factor_clks,
- data->clks->fixed_factor_clks_num,
- data);
+ hisi_clk_unregister_fixed_factor(data);
}

of_clk_del_provider(np);
- kfree(data->clk_data.clks);
+ kfree(data->clk_data);
kfree(data);
}
EXPORT_SYMBOL_GPL(hisi_clk_free);

int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
- int nums, struct hisi_clock_data *data)
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
+ struct clk_hw *clk;
int i;

- for (i = 0; i < nums; i++) {
- clk = clk_register_fixed_rate(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- clks[i].fixed_rate);
+ for (i = 0; i < num; i++) {
+ const struct hisi_fixed_rate_clock *p_clk = &clks[i];
+
+ clk = clk_hw_register_fixed_rate(NULL, p_clk->name, p_clk->parent_name,
+ p_clk->flags, p_clk->fixed_rate);
+
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
+ __func__, p_clk->name);
goto err;
}
- data->clk_data.clks[clks[i].id] = clk;
+
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;

err:
while (i--)
- clk_unregister_fixed_rate(data->clk_data.clks[clks[i].id]);
-
+ clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]);
return PTR_ERR(clk);
}
EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_rate);

int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
- int nums,
- struct hisi_clock_data *data)
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
+ struct clk_hw *clk;
int i;

- for (i = 0; i < nums; i++) {
- clk = clk_register_fixed_factor(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags, clks[i].mult,
- clks[i].div);
+ for (i = 0; i < num; i++) {
+ const struct hisi_fixed_factor_clock *p_clk = &clks[i];
+
+ clk = clk_hw_register_fixed_factor(NULL, p_clk->name, p_clk->parent_name,
+ p_clk->flags, p_clk->mult, p_clk->div);
+
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
+ __func__, p_clk->name);
goto err;
}
- data->clk_data.clks[clks[i].id] = clk;
+
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;

err:
while (i--)
- clk_unregister_fixed_factor(data->clk_data.clks[clks[i].id]);
-
+ clk_hw_unregister_fixed_rate(data->clk_data->hws[clks[i].id]);
return PTR_ERR(clk);
}
EXPORT_SYMBOL_GPL(hisi_clk_register_fixed_factor);

-int hisi_clk_register_mux(const struct hisi_mux_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_register_mux(struct device *dev, const struct hisi_mux_clock *clks,
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
void __iomem *base = data->base;
- int i;

- for (i = 0; i < nums; i++) {
- u32 mask = BIT(clks[i].width) - 1;
+ for (int i = 0; i < num; i++) {
+ const struct hisi_mux_clock *p_clk = &clks[i];
+ struct clk_hw *clk = __devm_clk_hw_register_mux(
+ dev, NULL, p_clk->name, p_clk->num_parents,
+ p_clk->parent_names, NULL, NULL, p_clk->flags,
+ base + p_clk->offset, p_clk->shift,
+ BIT(p_clk->width) - 1, p_clk->mux_flags, p_clk->table,
+ &hisi_clk_lock);

- clk = clk_register_mux_table(NULL, clks[i].name,
- clks[i].parent_names,
- clks[i].num_parents, clks[i].flags,
- base + clks[i].offset, clks[i].shift,
- mask, clks[i].mux_flags,
- clks[i].table, &hisi_clk_lock);
if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
+ pr_err("%s: failed to register clock %s\n", __func__,
+ p_clk->name);
+ return PTR_ERR(clk);
}

- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ if (p_clk->alias)
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL);
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;
-
-err:
- while (i--)
- clk_unregister_mux(data->clk_data.clks[clks[i].id]);
-
- return PTR_ERR(clk);
}
EXPORT_SYMBOL_GPL(hisi_clk_register_mux);

int hisi_clk_register_phase(struct device *dev,
- const struct hisi_phase_clock *clks,
- int nums, struct hisi_clock_data *data)
+ const struct hisi_phase_clock *clks, size_t num,
+ struct hisi_clock_data *data)
{
void __iomem *base = data->base;
- struct clk *clk;
- int i;

- for (i = 0; i < nums; i++) {
- clk = clk_register_hisi_phase(dev, &clks[i], base,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hisi_phase_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_hisi_phase(dev,
+ p_clk, base, &hisi_clk_lock);
+
if (IS_ERR(clk)) {
pr_err("%s: failed to register clock %s\n", __func__,
- clks[i].name);
+ p_clk->name);
return PTR_ERR(clk);
}

- data->clk_data.clks[clks[i].id] = clk;
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;
}
EXPORT_SYMBOL_GPL(hisi_clk_register_phase);

-int hisi_clk_register_divider(const struct hisi_divider_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_register_divider(struct device *dev,
+ const struct hisi_divider_clock *clks, size_t num,
+ struct hisi_clock_data *data)
{
- struct clk *clk;
void __iomem *base = data->base;
- int i;

- for (i = 0; i < nums; i++) {
- clk = clk_register_divider_table(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].shift, clks[i].width,
- clks[i].div_flags,
- clks[i].table,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hisi_divider_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_divider_table(
+ dev, p_clk->name, p_clk->parent_name, p_clk->flags,
+ base + p_clk->offset, p_clk->shift, p_clk->width,
+ p_clk->div_flags, p_clk->table, &hisi_clk_lock);
+
if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
+ pr_err("%s: failed to register clock %s\n", __func__,
+ p_clk->name);
+ return PTR_ERR(clk);
}

- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ if (p_clk->alias)
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL);
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;
-
-err:
- while (i--)
- clk_unregister_divider(data->clk_data.clks[clks[i].id]);
-
- return PTR_ERR(clk);
}
EXPORT_SYMBOL_GPL(hisi_clk_register_divider);

-int hisi_clk_register_gate(const struct hisi_gate_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_register_gate(struct device *dev,
+ const struct hisi_gate_clock *clks, size_t num,
+ struct hisi_clock_data *data)
{
- struct clk *clk;
void __iomem *base = data->base;
- int i;

- for (i = 0; i < nums; i++) {
- clk = clk_register_gate(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].bit_idx,
- clks[i].gate_flags,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hisi_gate_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_gate(
+ dev, p_clk->name, p_clk->parent_name, p_clk->flags,
+ base + p_clk->offset, p_clk->bit_idx, p_clk->gate_flags,
+ &hisi_clk_lock);
+
if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- goto err;
+ pr_err("%s: failed to register clock %s\n", __func__,
+ p_clk->name);
+ return PTR_ERR(clk);
}

- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ if (p_clk->alias)
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL);
+ data->clk_data->hws[p_clk->id] = clk;
}

return 0;
-
-err:
- while (i--)
- clk_unregister_gate(data->clk_data.clks[clks[i].id]);
-
- return PTR_ERR(clk);
}
EXPORT_SYMBOL_GPL(hisi_clk_register_gate);

-void hisi_clk_register_gate_sep(const struct hisi_gate_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hisi_clk_register_gate_sep(struct device *dev,
+ const struct hisi_gate_clock *clks, size_t num,
+ struct hisi_clock_data *data)
{
- struct clk *clk;
void __iomem *base = data->base;
- int i;

- for (i = 0; i < nums; i++) {
- clk = hisi_register_clkgate_sep(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].bit_idx,
- clks[i].gate_flags,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hisi_gate_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_hisi_gate_sep(
+ dev, p_clk->name, p_clk->parent_name, p_clk->flags,
+ base + p_clk->offset, p_clk->bit_idx, p_clk->gate_flags,
+ &hisi_clk_lock);
+
if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- continue;
+ pr_err("%s: failed to register clock %s\n", __func__,
+ p_clk->name);
+ return PTR_ERR(clk);
}

- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ if (p_clk->alias)
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL);
+ data->clk_data->hws[p_clk->id] = clk;
}
+
+ return 0;
}
EXPORT_SYMBOL_GPL(hisi_clk_register_gate_sep);

-void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
- int nums, struct hisi_clock_data *data)
+int hi6220_clk_register_divider(struct device *dev,
+ const struct hi6220_divider_clock *clks,
+ size_t num, struct hisi_clock_data *data)
{
- struct clk *clk;
void __iomem *base = data->base;
- int i;

- for (i = 0; i < nums; i++) {
- clk = hi6220_register_clkdiv(NULL, clks[i].name,
- clks[i].parent_name,
- clks[i].flags,
- base + clks[i].offset,
- clks[i].shift,
- clks[i].width,
- clks[i].mask_bit,
- &hisi_clk_lock);
+ for (int i = 0; i < num; i++) {
+ const struct hi6220_divider_clock *p_clk = &clks[i];
+ struct clk_hw *clk = devm_clk_hw_register_hi6220_divider(
+ dev, p_clk->name, p_clk->parent_name, p_clk->flags,
+ base + p_clk->offset, p_clk->shift, p_clk->width,
+ p_clk->mask_bit, &hisi_clk_lock);
+
if (IS_ERR(clk)) {
- pr_err("%s: failed to register clock %s\n",
- __func__, clks[i].name);
- continue;
+ pr_err("%s: failed to register clock %s\n", __func__,
+ p_clk->name);
+ return PTR_ERR(clk);
}

- if (clks[i].alias)
- clk_register_clkdev(clk, clks[i].alias, NULL);
-
- data->clk_data.clks[clks[i].id] = clk;
+ if (p_clk->alias)
+ clk_hw_register_clkdev(clk, p_clk->alias, NULL);
+ data->clk_data->hws[p_clk->id] = clk;
}
+
+ return 0;
}
+EXPORT_SYMBOL_GPL(hi6220_clk_register_divider);

static size_t hisi_clocks_get_nr(const struct hisi_clocks *clks)
{
@@ -406,38 +367,20 @@ static int hisi_clk_register(struct device *dev, const struct hisi_clocks *clks,
{
int ret;

- if (clks->mux_clks_num) {
- ret = hisi_clk_register_mux(clks->mux_clks,
- clks->mux_clks_num, data);
- if (ret)
- return ret;
- }
-
- if (clks->phase_clks_num) {
- ret = hisi_clk_register_phase(dev, clks->phase_clks,
- clks->phase_clks_num, data);
- if (ret)
- return ret;
- }
-
- if (clks->divider_clks_num) {
- ret = hisi_clk_register_divider(clks->divider_clks,
- clks->divider_clks_num, data);
- if (ret)
- return ret;
- }
-
- if (clks->gate_clks_num) {
- ret = hisi_clk_register_gate(clks->gate_clks,
- clks->gate_clks_num, data);
- if (ret)
- return ret;
- }
-
- if (clks->gate_sep_clks_num) {
- hisi_clk_register_gate_sep(clks->gate_sep_clks,
- clks->gate_sep_clks_num, data);
- }
+#define do_hisi_clk_register(type) do { \
+ if (clks->type##_clks_num) { \
+ ret = hisi_clk_register_##type(dev, clks->type##_clks, \
+ clks->type##_clks_num, data); \
+ if (ret) \
+ return ret; \
+ } \
+} while (0)
+
+ do_hisi_clk_register(mux);
+ do_hisi_clk_register(phase);
+ do_hisi_clk_register(divider);
+ do_hisi_clk_register(gate);
+ do_hisi_clk_register(gate_sep);

if (clks->clk_register_customized && clks->customized_clks_num) {
ret = clks->clk_register_customized(dev, clks->customized_clks,
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 87b17e9b79a3..911e1a45deb0 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -4,6 +4,7 @@
*
* Copyright (c) 2012-2013 Hisilicon Limited.
* Copyright (c) 2012-2013 Linaro Limited.
+ * Copyright (c) 2023 David Yang
*
* Author: Haojian Zhuang <[email protected]>
* Xin Li <[email protected]>
@@ -19,8 +20,18 @@
struct platform_device;
struct hisi_clocks;

+/*
+ * (Virtual) fixed clocks, often depended by crucial peripherals, require
+ * early initialization before device probing, thus cannot use devm APIs.
+ * Otherwise, kernel will defer those peripherals, causing boot failure.
+ *
+ * fixed_rate and fixed_factor clocks are driver-managed. They are freed by
+ * hisi_clk_free() altogether.
+ *
+ * Other clocks are devm-managed.
+ */
struct hisi_clock_data {
- struct clk_onecell_data clk_data;
+ struct clk_hw_onecell_data *clk_data;
void __iomem *base;
const struct hisi_clocks *clks;
};
@@ -138,57 +149,45 @@ struct hisi_clocks {
size_t num, struct hisi_clock_data *data);
};

-struct clk *hisi_register_clkgate_sep(struct device *, const char *,
- const char *, unsigned long,
- void __iomem *, u8,
- u8, spinlock_t *);
-struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
- const char *parent_name, unsigned long flags, void __iomem *reg,
- u8 shift, u8 width, u32 mask_bit, spinlock_t *lock);
-
-struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int);
-struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
-void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data);
-int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_mux(const struct hisi_mux_clock *, int,
- struct hisi_clock_data *);
-struct clk *clk_register_hisi_phase(struct device *dev,
- const struct hisi_phase_clock *clks,
+struct clk_hw *
+devm_clk_hw_register_hisi_phase(struct device *dev, const struct hisi_phase_clock *clks,
void __iomem *base, spinlock_t *lock);
+struct clk_hw *
+devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock);
+struct clk_hw *
+devm_clk_hw_register_hi6220_divider(struct device *dev, const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift,
+ u8 width, u32 mask_bit, spinlock_t *lock);
+
+struct hisi_clock_data *hisi_clk_init(struct device_node *np, size_t nr);
+void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data);
+
+int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+
+int hisi_clk_register_mux(struct device *dev, const struct hisi_mux_clock *clks,
+ size_t num, struct hisi_clock_data *data);
int hisi_clk_register_phase(struct device *dev,
- const struct hisi_phase_clock *clks,
- int nums, struct hisi_clock_data *data);
-int hisi_clk_register_divider(const struct hisi_divider_clock *,
- int, struct hisi_clock_data *);
-int hisi_clk_register_gate(const struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
-void hisi_clk_register_gate_sep(const struct hisi_gate_clock *,
- int, struct hisi_clock_data *);
-void hi6220_clk_register_divider(const struct hi6220_divider_clock *,
- int, struct hisi_clock_data *);
-
-#define hisi_clk_unregister(type) \
-static inline \
-void hisi_clk_unregister_##type(const struct hisi_##type##_clock *clks, \
- int nums, struct hisi_clock_data *data) \
-{ \
- struct clk **clocks = data->clk_data.clks; \
- int i; \
- for (i = 0; i < nums; i++) { \
- int id = clks[i].id; \
- if (clocks[id]) \
- clk_unregister_##type(clocks[id]); \
- } \
-}
-
-hisi_clk_unregister(fixed_rate)
-hisi_clk_unregister(fixed_factor)
-hisi_clk_unregister(mux)
-hisi_clk_unregister(divider)
-hisi_clk_unregister(gate)
+ const struct hisi_phase_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_divider(struct device *dev,
+ const struct hisi_divider_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_gate(struct device *dev,
+ const struct hisi_gate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hisi_clk_register_gate_sep(struct device *dev,
+ const struct hisi_gate_clock *clks,
+ size_t num, struct hisi_clock_data *data);
+int hi6220_clk_register_divider(struct device *dev,
+ const struct hi6220_divider_clock *clks,
+ size_t num, struct hisi_clock_data *data);

/* helper functions for platform driver */

diff --git a/drivers/clk/hisilicon/clkdivider-hi6220.c b/drivers/clk/hisilicon/clkdivider-hi6220.c
index 5348bafe694f..3c03b3e5b841 100644
--- a/drivers/clk/hisilicon/clkdivider-hi6220.c
+++ b/drivers/clk/hisilicon/clkdivider-hi6220.c
@@ -9,7 +9,7 @@

#include <linux/kernel.h>
#include <linux/clk-provider.h>
-#include <linux/slab.h>
+#include <linux/device.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/spinlock.h>
@@ -97,19 +97,19 @@ static const struct clk_ops hi6220_clkdiv_ops = {
.set_rate = hi6220_clkdiv_set_rate,
};

-struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
+struct clk_hw *devm_clk_hw_register_hi6220_divider(struct device *dev, const char *name,
const char *parent_name, unsigned long flags, void __iomem *reg,
u8 shift, u8 width, u32 mask_bit, spinlock_t *lock)
{
struct hi6220_clk_divider *div;
- struct clk *clk;
struct clk_init_data init;
struct clk_div_table *table;
u32 max_div, min_div;
int i;
+ int ret;

/* allocate the divider */
- div = kzalloc(sizeof(*div), GFP_KERNEL);
+ div = devm_kzalloc(dev, sizeof(*div), GFP_KERNEL);
if (!div)
return ERR_PTR(-ENOMEM);

@@ -117,11 +117,9 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
max_div = div_mask(width) + 1;
min_div = 1;

- table = kcalloc(max_div + 1, sizeof(*table), GFP_KERNEL);
- if (!table) {
- kfree(div);
+ table = devm_kcalloc(dev, max_div + 1, sizeof(*table), GFP_KERNEL);
+ if (!table)
return ERR_PTR(-ENOMEM);
- }

for (i = 0; i < max_div; i++) {
table[i].div = min_div + i;
@@ -144,11 +142,9 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,
div->table = table;

/* register the clock */
- clk = clk_register(dev, &div->hw);
- if (IS_ERR(clk)) {
- kfree(table);
- kfree(div);
- }
+ ret = devm_clk_hw_register(dev, &div->hw);
+ if (ret)
+ return ERR_PTR(ret);

- return clk;
+ return &div->hw;
}
diff --git a/drivers/clk/hisilicon/clkgate-separated.c b/drivers/clk/hisilicon/clkgate-separated.c
index 90d858522967..dc64a8a0ab58 100644
--- a/drivers/clk/hisilicon/clkgate-separated.c
+++ b/drivers/clk/hisilicon/clkgate-separated.c
@@ -11,8 +11,8 @@

#include <linux/kernel.h>
#include <linux/clk-provider.h>
+#include <linux/device.h>
#include <linux/io.h>
-#include <linux/slab.h>

#include "clk.h"

@@ -80,17 +80,18 @@ static const struct clk_ops clkgate_separated_ops = {
.is_enabled = clkgate_separated_is_enabled,
};

-struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name,
- const char *parent_name,
- unsigned long flags,
- void __iomem *reg, u8 bit_idx,
- u8 clk_gate_flags, spinlock_t *lock)
+struct clk_hw *
+devm_clk_hw_register_hisi_gate_sep(struct device *dev, const char *name,
+ const char *parent_name,
+ unsigned long flags,
+ void __iomem *reg, u8 bit_idx,
+ u8 clk_gate_flags, spinlock_t *lock)
{
struct clkgate_separated *sclk;
- struct clk *clk;
struct clk_init_data init;
+ int ret;

- sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
+ sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
if (!sclk)
return ERR_PTR(-ENOMEM);

@@ -106,8 +107,9 @@ struct clk *hisi_register_clkgate_sep(struct device *dev, const char *name,
sclk->hw.init = &init;
sclk->lock = lock;

- clk = clk_register(dev, &sclk->hw);
- if (IS_ERR(clk))
- kfree(sclk);
- return clk;
+ ret = devm_clk_hw_register(dev, &sclk->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &sclk->hw;
}
--
2.40.1


2023-07-31 13:25:17

by David Yang

[permalink] [raw]
Subject: [PATCH v6 12/13] clk: hisilicon: hix5hd2: Convert into platform driver module

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk-hix5hd2.c | 85 ++++++++++++++++++-----------
1 file changed, 52 insertions(+), 33 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hix5hd2.c b/drivers/clk/hisilicon/clk-hix5hd2.c
index 64bdd3f05725..6f988a7574b4 100644
--- a/drivers/clk/hisilicon/clk-hix5hd2.c
+++ b/drivers/clk/hisilicon/clk-hix5hd2.c
@@ -4,13 +4,17 @@
* Copyright (c) 2014 Hisilicon Limited.
*/

-#include <linux/of_address.h>
#include <dt-bindings/clock/hix5hd2-clock.h>
+
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+
#include "clk.h"

-static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
+static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] = {
{ HIX5HD2_FIXED_1200M, "1200m", NULL, 0, 1200000000, },
{ HIX5HD2_FIXED_400M, "400m", NULL, 0, 400000000, },
{ HIX5HD2_FIXED_48M, "48m", NULL, 0, 48000000, },
@@ -43,19 +47,19 @@ static struct hisi_fixed_rate_clock hix5hd2_fixed_rate_clks[] __initdata = {
{ HIX5HD2_FIXED_83M, "83m", NULL, 0, 83333333, },
};

-static const char *const sfc_mux_p[] __initconst = {
+static const char *const sfc_mux_p[] = {
"24m", "150m", "200m", "100m", "75m", };
static u32 sfc_mux_table[] = {0, 4, 5, 6, 7};

-static const char *const sdio_mux_p[] __initconst = {
+static const char *const sdio_mux_p[] = {
"75m", "100m", "50m", "15m", };
static u32 sdio_mux_table[] = {0, 1, 2, 3};

-static const char *const fephy_mux_p[] __initconst = { "25m", "125m"};
+static const char *const fephy_mux_p[] = { "25m", "125m"};
static u32 fephy_mux_table[] = {0, 1};


-static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
+static struct hisi_mux_clock hix5hd2_mux_clks[] = {
{ HIX5HD2_SFC_MUX, "sfc_mux", sfc_mux_p, ARRAY_SIZE(sfc_mux_p),
CLK_SET_RATE_PARENT, 0x5c, 8, 3, 0, sfc_mux_table, },
{ HIX5HD2_MMC_MUX, "mmc_mux", sdio_mux_p, ARRAY_SIZE(sdio_mux_p),
@@ -67,7 +71,7 @@ static struct hisi_mux_clock hix5hd2_mux_clks[] __initdata = {
CLK_SET_RATE_PARENT, 0x120, 8, 2, 0, fephy_mux_table, },
};

-static struct hisi_gate_clock hix5hd2_gate_clks[] __initdata = {
+static struct hisi_gate_clock hix5hd2_gate_clks[] = {
/* sfc */
{ HIX5HD2_SFC_CLK, "clk_sfc", "sfc_mux",
CLK_SET_RATE_PARENT, 0x5c, 0, 0, },
@@ -153,7 +157,7 @@ struct hix5hd2_clk_complex {
u32 phy_rst_mask;
};

-static struct hix5hd2_complex_clock hix5hd2_complex_clks[] __initdata = {
+static struct hix5hd2_complex_clock hix5hd2_complex_clks[] = {
{"clk_mac0", "clk_fephy", HIX5HD2_MAC0_CLK,
0xcc, 0xa, 0x500, 0x120, 0, 0x10, TYPE_ETHER},
{"clk_mac1", "clk_fwd_sys", HIX5HD2_MAC1_CLK,
@@ -249,21 +253,22 @@ static const struct clk_ops clk_complex_ops = {
.disable = clk_complex_disable,
};

-static void __init
-hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
+static int
+hix5hd2_clk_register_complex(struct device *dev, const void *clocks, size_t num,
struct hisi_clock_data *data)
{
+ const struct hix5hd2_complex_clock *clks = clocks;
void __iomem *base = data->base;
int i;

- for (i = 0; i < nums; i++) {
+ for (i = 0; i < num; i++) {
struct hix5hd2_clk_complex *p_clk;
struct clk *clk;
struct clk_init_data init;

p_clk = kzalloc(sizeof(*p_clk), GFP_KERNEL);
if (!p_clk)
- return;
+ return -ENOMEM;

init.name = clks[i].name;
if (clks[i].type == TYPE_ETHER)
@@ -289,31 +294,45 @@ hix5hd2_clk_register_complex(struct hix5hd2_complex_clock *clks, int nums,
kfree(p_clk);
pr_err("%s: failed to register clock %s\n",
__func__, clks[i].name);
- continue;
+ return PTR_ERR(p_clk);
}

data->clk_data.clks[clks[i].id] = clk;
}
-}

-static void __init hix5hd2_clk_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
-
- clk_data = hisi_clk_init(np, HIX5HD2_NR_CLKS);
- if (!clk_data)
- return;
-
- hisi_clk_register_fixed_rate(hix5hd2_fixed_rate_clks,
- ARRAY_SIZE(hix5hd2_fixed_rate_clks),
- clk_data);
- hisi_clk_register_mux(hix5hd2_mux_clks, ARRAY_SIZE(hix5hd2_mux_clks),
- clk_data);
- hisi_clk_register_gate(hix5hd2_gate_clks,
- ARRAY_SIZE(hix5hd2_gate_clks), clk_data);
- hix5hd2_clk_register_complex(hix5hd2_complex_clks,
- ARRAY_SIZE(hix5hd2_complex_clks),
- clk_data);
+ return 0;
}

-CLK_OF_DECLARE(hix5hd2_clk, "hisilicon,hix5hd2-clock", hix5hd2_clk_init);
+static const struct hisi_clocks hix5hd2_clks = {
+ .nr = HIX5HD2_NR_CLKS,
+ .fixed_rate_clks = hix5hd2_fixed_rate_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hix5hd2_fixed_rate_clks),
+ .mux_clks = hix5hd2_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hix5hd2_mux_clks),
+ .gate_clks = hix5hd2_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hix5hd2_gate_clks),
+ .customized_clks = hix5hd2_complex_clks,
+ .customized_clks_num = ARRAY_SIZE(hix5hd2_complex_clks),
+ .clk_register_customized = hix5hd2_clk_register_complex,
+};
+
+static const struct of_device_id hix5hd2_clk_match_table[] = {
+ { .compatible = "hisilicon,hix5hd2-clock",
+ .data = &hix5hd2_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hix5hd2_clk_match_table);
+
+static struct platform_driver hix5hd2_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove_new = hisi_clk_remove,
+ .driver = {
+ .name = "hix5hd2-clock",
+ .of_match_table = hix5hd2_clk_match_table,
+ },
+};
+
+module_platform_driver(hix5hd2_clk_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("HiSilicon Hix5hd2 Clock Driver");
--
2.40.1


2023-07-31 13:25:50

by David Yang

[permalink] [raw]
Subject: [PATCH v6 11/13] clk: hisilicon: hip04: Convert into platform driver module

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk-hip04.c | 39 +++++++++++++++++++------------
1 file changed, 24 insertions(+), 15 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hip04.c b/drivers/clk/hisilicon/clk-hip04.c
index 785b9faf3ea5..9aa2481781cb 100644
--- a/drivers/clk/hisilicon/clk-hip04.c
+++ b/drivers/clk/hisilicon/clk-hip04.c
@@ -10,11 +10,8 @@

#include <linux/kernel.h>
#include <linux/clk-provider.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/of_address.h>
+#include <linux/module.h>
#include <linux/of_device.h>
-#include <linux/slab.h>

#include <dt-bindings/clock/hip04-clock.h>

@@ -27,16 +24,28 @@ static struct hisi_fixed_rate_clock hip04_fixed_rate_clks[] __initdata = {
{ HIP04_CLK_168M, "clk168m", NULL, 0, 168750000, },
};

-static void __init hip04_clk_init(struct device_node *np)
-{
- struct hisi_clock_data *clk_data;
+static const struct hisi_clocks hip04_clks = {
+ .fixed_rate_clks = hip04_fixed_rate_clks,
+ .fixed_factor_clks_num = ARRAY_SIZE(hip04_fixed_rate_clks),
+};
+
+static const struct of_device_id hip04_clk_match_table[] = {
+ { .compatible = "hisilicon,hip04-clock",
+ .data = &hip04_clks },
+ { }
+};
+MODULE_DEVICE_TABLE(of, hip04_clk_match_table);
+
+static struct platform_driver hip04_clk_driver = {
+ .probe = hisi_clk_probe,
+ .remove_new = hisi_clk_remove,
+ .driver = {
+ .name = "hip04-clock",
+ .of_match_table = hip04_clk_match_table,
+ },
+};

- clk_data = hisi_clk_init(np, HIP04_NR_CLKS);
- if (!clk_data)
- return;
+module_platform_driver(hip04_clk_driver);

- hisi_clk_register_fixed_rate(hip04_fixed_rate_clks,
- ARRAY_SIZE(hip04_fixed_rate_clks),
- clk_data);
-}
-CLK_OF_DECLARE(hip04_clk, "hisilicon,hip04-clock", hip04_clk_init);
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("HiSilicon HiP04 Clock Driver");
--
2.40.1


2023-07-31 13:28:49

by David Yang

[permalink] [raw]
Subject: [PATCH v6 03/13] clk: hisilicon: hi3798cv200: Use helper functions

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/crg-hi3798cv200.c | 196 +++---------------------
1 file changed, 20 insertions(+), 176 deletions(-)

diff --git a/drivers/clk/hisilicon/crg-hi3798cv200.c b/drivers/clk/hisilicon/crg-hi3798cv200.c
index a0b16be1e25d..c2079bf293b2 100644
--- a/drivers/clk/hisilicon/crg-hi3798cv200.c
+++ b/drivers/clk/hisilicon/crg-hi3798cv200.c
@@ -12,7 +12,6 @@
#include <linux/platform_device.h>
#include "clk.h"
#include "crg.h"
-#include "reset.h"

/* hi3798CV200 core CRG */
#define HI3798CV200_INNER_CLK_OFFSET 64
@@ -41,6 +40,7 @@

#define HI3798CV200_CRG_NR_CLKS 128

+#define HI3798CV200_SYSCTRL_NR_CLKS 16
static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {
{ HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },
{ HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },
@@ -193,90 +193,18 @@ static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {
CLK_SET_RATE_PARENT, 0xb0, 18, 0 },
};

-static struct hisi_clock_data *hi3798cv200_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- /* hisi_phase_clock is resource managed */
- ret = hisi_clk_register_phase(&pdev->dev,
- hi3798cv200_phase_clks,
- ARRAY_SIZE(hi3798cv200_phase_clks),
- clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,
- ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
- clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3798cv200_mux_clks,
- ARRAY_SIZE(hi3798cv200_mux_clks),
- clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3798cv200_gate_clks,
- ARRAY_SIZE(hi3798cv200_gate_clks),
- clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3798cv200_gate_clks,
- ARRAY_SIZE(hi3798cv200_gate_clks),
- clk_data);
-unregister_mux:
- hisi_clk_unregister_mux(hi3798cv200_mux_clks,
- ARRAY_SIZE(hi3798cv200_mux_clks),
- clk_data);
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
- ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
- clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3798cv200_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3798cv200_gate_clks,
- ARRAY_SIZE(hi3798cv200_gate_clks),
- crg->clk_data);
- hisi_clk_unregister_mux(hi3798cv200_mux_clks,
- ARRAY_SIZE(hi3798cv200_mux_clks),
- crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,
- ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
- crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {
- .register_clks = hi3798cv200_clk_register,
- .unregister_clks = hi3798cv200_clk_unregister,
+static const struct hisi_clocks hi3798cv200_crg_clks = {
+ .nr = HI3798CV200_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3798cv200_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3798cv200_fixed_rate_clks),
+ .mux_clks = hi3798cv200_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3798cv200_mux_clks),
+ .phase_clks = hi3798cv200_phase_clks,
+ .phase_clks_num = ARRAY_SIZE(hi3798cv200_phase_clks),
+ .gate_clks = hi3798cv200_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798cv200_gate_clks),
};

-/* hi3798CV200 sysctrl CRG */
-
-#define HI3798CV200_SYSCTRL_NR_CLKS 16
-
static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
{ HISTB_IR_CLK, "clk_ir", "24m",
CLK_SET_RATE_PARENT, 0x48, 4, 0, },
@@ -286,115 +214,31 @@ static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {
CLK_SET_RATE_PARENT, 0x48, 10, 0, },
};

-static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,
- ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
- clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
- ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
- clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,
- ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
- crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {
- .register_clks = hi3798cv200_sysctrl_clk_register,
- .unregister_clks = hi3798cv200_sysctrl_clk_unregister,
+static const struct hisi_clocks hi3798cv200_sysctrl_clks = {
+ .nr = HI3798CV200_SYSCTRL_NR_CLKS,
+ .gate_clks = hi3798cv200_sysctrl_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),
};

static const struct of_device_id hi3798cv200_crg_match_table[] = {
{ .compatible = "hisilicon,hi3798cv200-crg",
- .data = &hi3798cv200_crg_funcs },
+ .data = &hi3798cv200_crg_clks },
{ .compatible = "hisilicon,hi3798cv200-sysctrl",
- .data = &hi3798cv200_sysctrl_funcs },
+ .data = &hi3798cv200_sysctrl_clks },
{ }
};
MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);

-static int hi3798cv200_crg_probe(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->funcs = of_device_get_match_data(&pdev->dev);
- if (!crg->funcs)
- return -ENOENT;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = crg->funcs->register_clks(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3798cv200_crg_remove(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- crg->funcs->unregister_clks(pdev);
-}
-
static struct platform_driver hi3798cv200_crg_driver = {
- .probe = hi3798cv200_crg_probe,
- .remove_new = hi3798cv200_crg_remove,
+ .probe = hisi_crg_probe,
+ .remove_new = hisi_crg_remove,
.driver = {
.name = "hi3798cv200-crg",
.of_match_table = hi3798cv200_crg_match_table,
},
};

-static int __init hi3798cv200_crg_init(void)
-{
- return platform_driver_register(&hi3798cv200_crg_driver);
-}
-core_initcall(hi3798cv200_crg_init);
-
-static void __exit hi3798cv200_crg_exit(void)
-{
- platform_driver_unregister(&hi3798cv200_crg_driver);
-}
-module_exit(hi3798cv200_crg_exit);
+module_platform_driver(hi3798cv200_crg_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");
--
2.40.1


2023-07-31 13:35:53

by David Yang

[permalink] [raw]
Subject: [PATCH v6 02/13] clk: hisilicon: hi3516cv300: Use helper functions

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/crg-hi3516cv300.c | 171 +++---------------------
1 file changed, 17 insertions(+), 154 deletions(-)

diff --git a/drivers/clk/hisilicon/crg-hi3516cv300.c b/drivers/clk/hisilicon/crg-hi3516cv300.c
index fe1bd3e3f988..93db2be9229c 100644
--- a/drivers/clk/hisilicon/crg-hi3516cv300.c
+++ b/drivers/clk/hisilicon/crg-hi3516cv300.c
@@ -12,7 +12,6 @@
#include <linux/platform_device.h>
#include "clk.h"
#include "crg.h"
-#include "reset.h"

/* hi3516CV300 core CRG */
#define HI3516CV300_INNER_CLK_OFFSET 64
@@ -126,67 +125,14 @@ static const struct hisi_gate_clock hi3516cv300_gate_clks[] = {
{ HI3516CV300_USB2_PHY_CLK, "clk_usb2_phy", NULL, 0, 0xb8, 7, 0, },
};

-static struct hisi_clock_data *hi3516cv300_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3516CV300_CRG_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_gate:
- hisi_clk_unregister_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), clk_data);
-unregister_mux:
- hisi_clk_unregister_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), clk_data);
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3516cv300_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3516cv300_gate_clks,
- ARRAY_SIZE(hi3516cv300_gate_clks), crg->clk_data);
- hisi_clk_unregister_mux(hi3516cv300_mux_clks,
- ARRAY_SIZE(hi3516cv300_mux_clks), crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3516cv300_fixed_rate_clks,
- ARRAY_SIZE(hi3516cv300_fixed_rate_clks), crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3516cv300_crg_funcs = {
- .register_clks = hi3516cv300_clk_register,
- .unregister_clks = hi3516cv300_clk_unregister,
+static const struct hisi_clocks hi3516cv300_crg_clks = {
+ .nr = HI3516CV300_CRG_NR_CLKS,
+ .fixed_rate_clks = hi3516cv300_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3516cv300_fixed_rate_clks),
+ .mux_clks = hi3516cv300_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3516cv300_mux_clks),
+ .gate_clks = hi3516cv300_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3516cv300_gate_clks),
};

/* hi3516CV300 sysctrl CRG */
@@ -200,118 +146,35 @@ static const struct hisi_mux_clock hi3516cv300_sysctrl_mux_clks[] = {
CLK_SET_RATE_PARENT, 0x0, 23, 1, 0, wdt_mux_table, },
};

-static struct hisi_clock_data *hi3516cv300_sysctrl_clk_register(
- struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3516CV300_SYSCTRL_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
- if (ret)
- return ERR_PTR(ret);
-
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_mux;
-
- return clk_data;
-
-unregister_mux:
- hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks), clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3516cv300_sysctrl_clk_unregister(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_mux(hi3516cv300_sysctrl_mux_clks,
- ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
- crg->clk_data);
-}
-
-static const struct hisi_crg_funcs hi3516cv300_sysctrl_funcs = {
- .register_clks = hi3516cv300_sysctrl_clk_register,
- .unregister_clks = hi3516cv300_sysctrl_clk_unregister,
+static const struct hisi_clocks hi3516cv300_sysctrl_clks = {
+ .nr = HI3516CV300_SYSCTRL_NR_CLKS,
+ .mux_clks = hi3516cv300_sysctrl_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3516cv300_sysctrl_mux_clks),
};

static const struct of_device_id hi3516cv300_crg_match_table[] = {
{
.compatible = "hisilicon,hi3516cv300-crg",
- .data = &hi3516cv300_crg_funcs
+ .data = &hi3516cv300_crg_clks,
},
{
.compatible = "hisilicon,hi3516cv300-sysctrl",
- .data = &hi3516cv300_sysctrl_funcs
+ .data = &hi3516cv300_sysctrl_clks,
},
{ }
};
MODULE_DEVICE_TABLE(of, hi3516cv300_crg_match_table);

-static int hi3516cv300_crg_probe(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->funcs = of_device_get_match_data(&pdev->dev);
- if (!crg->funcs)
- return -ENOENT;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = crg->funcs->register_clks(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3516cv300_crg_remove(struct platform_device *pdev)
-{
- struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- crg->funcs->unregister_clks(pdev);
-}
-
static struct platform_driver hi3516cv300_crg_driver = {
- .probe = hi3516cv300_crg_probe,
- .remove_new = hi3516cv300_crg_remove,
+ .probe = hisi_crg_probe,
+ .remove_new = hisi_crg_remove,
.driver = {
.name = "hi3516cv300-crg",
.of_match_table = hi3516cv300_crg_match_table,
},
};

-static int __init hi3516cv300_crg_init(void)
-{
- return platform_driver_register(&hi3516cv300_crg_driver);
-}
-core_initcall(hi3516cv300_crg_init);
-
-static void __exit hi3516cv300_crg_exit(void)
-{
- platform_driver_unregister(&hi3516cv300_crg_driver);
-}
-module_exit(hi3516cv300_crg_exit);
+module_platform_driver(hi3516cv300_crg_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3516CV300 CRG Driver");
--
2.40.1


2023-07-31 13:37:26

by David Yang

[permalink] [raw]
Subject: [PATCH v6 01/13] clk: hisilicon: Add helper functions for platform driver

Helper functions extract common operations on platform drivers.

During migration to devm APIs, (virtual) fixed clocks were found hard on
devm APIs, since they often depended by crucial peripherals, thus require
early initialization before device probing, and cannot use devm APIs.

One solution to this problem is to add a "fixed-clock" node to device tree,
independent to clock device, and make those peripherals depend on that.
However, there is also some devices that do use fixed clocks provided by
drivers, for example clk-hi3660.c .

To simplify codes, we migrate clocks of other types to devm APIs, while
keep fixed clocks self-managed, alongside with struct hisi_clock_data, and
remove devm-managed hisi_clock_data.

hisi_clk_alloc() will be removed in the following patch.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk.c | 157 ++++++++++++++++++++++++++++++++++
drivers/clk/hisilicon/clk.h | 46 +++++++++-
drivers/clk/hisilicon/crg.h | 5 ++
drivers/clk/hisilicon/reset.c | 42 +++++++++
4 files changed, 248 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/hisilicon/clk.c b/drivers/clk/hisilicon/clk.c
index 54d9fdc93599..aa8908714cd0 100644
--- a/drivers/clk/hisilicon/clk.c
+++ b/drivers/clk/hisilicon/clk.c
@@ -88,6 +88,25 @@ struct hisi_clock_data *hisi_clk_init(struct device_node *np,
}
EXPORT_SYMBOL_GPL(hisi_clk_init);

+void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data)
+{
+ if (data->clks) {
+ if (data->clks->fixed_rate_clks_num)
+ hisi_clk_unregister_fixed_rate(data->clks->fixed_rate_clks,
+ data->clks->fixed_rate_clks_num,
+ data);
+ if (data->clks->fixed_factor_clks_num)
+ hisi_clk_unregister_fixed_factor(data->clks->fixed_factor_clks,
+ data->clks->fixed_factor_clks_num,
+ data);
+ }
+
+ of_clk_del_provider(np);
+ kfree(data->clk_data.clks);
+ kfree(data);
+}
+EXPORT_SYMBOL_GPL(hisi_clk_free);
+
int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *clks,
int nums, struct hisi_clock_data *data)
{
@@ -341,3 +360,141 @@ void __init hi6220_clk_register_divider(const struct hi6220_divider_clock *clks,
data->clk_data.clks[clks[i].id] = clk;
}
}
+
+static size_t hisi_clocks_get_nr(const struct hisi_clocks *clks)
+{
+ if (clks->nr)
+ return clks->nr;
+
+ return clks->fixed_rate_clks_num + clks->fixed_factor_clks_num +
+ clks->mux_clks_num + clks->phase_clks_num +
+ clks->divider_clks_num + clks->gate_clks_num +
+ clks->gate_sep_clks_num + clks->customized_clks_num;
+}
+
+int hisi_clk_early_init(struct device_node *np, const struct hisi_clocks *clks)
+{
+ struct hisi_clock_data *data;
+ int ret;
+
+ data = hisi_clk_init(np, hisi_clocks_get_nr(clks));
+ if (!data)
+ return -ENOMEM;
+ data->clks = clks;
+
+ ret = hisi_clk_register_fixed_rate(clks->fixed_rate_clks,
+ clks->fixed_rate_clks_num, data);
+ if (ret)
+ goto err;
+
+ ret = hisi_clk_register_fixed_factor(clks->fixed_factor_clks,
+ clks->fixed_factor_clks_num, data);
+ if (ret)
+ goto err;
+
+ np->data = data;
+ return 0;
+
+err:
+ hisi_clk_free(np, data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_clk_early_init);
+
+static int hisi_clk_register(struct device *dev, const struct hisi_clocks *clks,
+ struct hisi_clock_data *data)
+{
+ int ret;
+
+ if (clks->mux_clks_num) {
+ ret = hisi_clk_register_mux(clks->mux_clks,
+ clks->mux_clks_num, data);
+ if (ret)
+ return ret;
+ }
+
+ if (clks->phase_clks_num) {
+ ret = hisi_clk_register_phase(dev, clks->phase_clks,
+ clks->phase_clks_num, data);
+ if (ret)
+ return ret;
+ }
+
+ if (clks->divider_clks_num) {
+ ret = hisi_clk_register_divider(clks->divider_clks,
+ clks->divider_clks_num, data);
+ if (ret)
+ return ret;
+ }
+
+ if (clks->gate_clks_num) {
+ ret = hisi_clk_register_gate(clks->gate_clks,
+ clks->gate_clks_num, data);
+ if (ret)
+ return ret;
+ }
+
+ if (clks->gate_sep_clks_num) {
+ hisi_clk_register_gate_sep(clks->gate_sep_clks,
+ clks->gate_sep_clks_num, data);
+ }
+
+ if (clks->clk_register_customized && clks->customized_clks_num) {
+ ret = clks->clk_register_customized(dev, clks->customized_clks,
+ clks->customized_clks_num, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int hisi_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ const struct hisi_clocks *clks;
+ struct hisi_clock_data *data;
+ int ret;
+
+ clks = of_device_get_match_data(dev);
+ if (!clks)
+ return -ENOENT;
+
+ if (!np->data) {
+ ret = hisi_clk_early_init(np, clks);
+ if (ret)
+ return ret;
+ }
+
+ data = np->data;
+ np->data = NULL;
+
+ if (clks->prologue) {
+ ret = clks->prologue(dev, data);
+ if (ret)
+ goto err;
+ }
+
+ ret = hisi_clk_register(dev, clks, data);
+ if (ret)
+ goto err;
+
+ platform_set_drvdata(pdev, data);
+ return 0;
+
+err:
+ hisi_clk_free(np, data);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_clk_probe);
+
+void hisi_clk_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct device_node *np = dev->of_node;
+ struct hisi_clock_data *data = platform_get_drvdata(pdev);
+
+ hisi_clk_free(np, data);
+}
+EXPORT_SYMBOL_GPL(hisi_clk_remove);
diff --git a/drivers/clk/hisilicon/clk.h b/drivers/clk/hisilicon/clk.h
index 7a9b42e1b027..87b17e9b79a3 100644
--- a/drivers/clk/hisilicon/clk.h
+++ b/drivers/clk/hisilicon/clk.h
@@ -17,10 +17,12 @@
#include <linux/spinlock.h>

struct platform_device;
+struct hisi_clocks;

struct hisi_clock_data {
- struct clk_onecell_data clk_data;
- void __iomem *base;
+ struct clk_onecell_data clk_data;
+ void __iomem *base;
+ const struct hisi_clocks *clks;
};

struct hisi_fixed_rate_clock {
@@ -103,6 +105,39 @@ struct hisi_gate_clock {
const char *alias;
};

+struct hisi_clocks {
+ /* if 0, sum all *_num */
+ size_t nr;
+
+ int (*prologue)(struct device *dev, struct hisi_clock_data *data);
+
+ const struct hisi_fixed_rate_clock *fixed_rate_clks;
+ size_t fixed_rate_clks_num;
+
+ const struct hisi_fixed_factor_clock *fixed_factor_clks;
+ size_t fixed_factor_clks_num;
+
+ const struct hisi_mux_clock *mux_clks;
+ size_t mux_clks_num;
+
+ const struct hisi_phase_clock *phase_clks;
+ size_t phase_clks_num;
+
+ const struct hisi_divider_clock *divider_clks;
+ size_t divider_clks_num;
+
+ const struct hisi_gate_clock *gate_clks;
+ size_t gate_clks_num;
+
+ const struct hisi_gate_clock *gate_sep_clks;
+ size_t gate_sep_clks_num;
+
+ const void *customized_clks;
+ size_t customized_clks_num;
+ int (*clk_register_customized)(struct device *dev, const void *clks,
+ size_t num, struct hisi_clock_data *data);
+};
+
struct clk *hisi_register_clkgate_sep(struct device *, const char *,
const char *, unsigned long,
void __iomem *, u8,
@@ -113,6 +148,7 @@ struct clk *hi6220_register_clkdiv(struct device *dev, const char *name,

struct hisi_clock_data *hisi_clk_alloc(struct platform_device *, int);
struct hisi_clock_data *hisi_clk_init(struct device_node *, int);
+void hisi_clk_free(struct device_node *np, struct hisi_clock_data *data);
int hisi_clk_register_fixed_rate(const struct hisi_fixed_rate_clock *,
int, struct hisi_clock_data *);
int hisi_clk_register_fixed_factor(const struct hisi_fixed_factor_clock *,
@@ -154,4 +190,10 @@ hisi_clk_unregister(mux)
hisi_clk_unregister(divider)
hisi_clk_unregister(gate)

+/* helper functions for platform driver */
+
+int hisi_clk_early_init(struct device_node *np, const struct hisi_clocks *clks);
+int hisi_clk_probe(struct platform_device *pdev);
+void hisi_clk_remove(struct platform_device *pdev);
+
#endif /* __HISI_CLK_H */
diff --git a/drivers/clk/hisilicon/crg.h b/drivers/clk/hisilicon/crg.h
index 803f6ba6d7a2..bd8e76b1f6d7 100644
--- a/drivers/clk/hisilicon/crg.h
+++ b/drivers/clk/hisilicon/crg.h
@@ -22,4 +22,9 @@ struct hisi_crg_dev {
const struct hisi_crg_funcs *funcs;
};

+/* helper functions for platform driver */
+
+int hisi_crg_probe(struct platform_device *pdev);
+void hisi_crg_remove(struct platform_device *pdev);
+
#endif /* __HISI_CRG_H */
diff --git a/drivers/clk/hisilicon/reset.c b/drivers/clk/hisilicon/reset.c
index 93cee17db8b1..c7d4c9ea7183 100644
--- a/drivers/clk/hisilicon/reset.c
+++ b/drivers/clk/hisilicon/reset.c
@@ -6,11 +6,15 @@
*/

#include <linux/io.h>
+#include <linux/kernel.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/reset-controller.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
+
+#include "clk.h"
+#include "crg.h"
#include "reset.h"

#define HISI_RESET_BIT_MASK 0x1f
@@ -116,3 +120,41 @@ void hisi_reset_exit(struct hisi_reset_controller *rstc)
reset_controller_unregister(&rstc->rcdev);
}
EXPORT_SYMBOL_GPL(hisi_reset_exit);
+
+int hisi_crg_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct hisi_crg_dev *crg;
+ int ret;
+
+ crg = devm_kmalloc(dev, sizeof(*crg), GFP_KERNEL);
+ if (!crg)
+ return -ENOMEM;
+
+ ret = hisi_clk_probe(pdev);
+ if (ret)
+ return ret;
+
+ crg->rstc = hisi_reset_init(pdev);
+ if (!crg->rstc) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ platform_set_drvdata(pdev, crg);
+ return 0;
+
+err:
+ hisi_clk_remove(pdev);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(hisi_crg_probe);
+
+void hisi_crg_remove(struct platform_device *pdev)
+{
+ struct hisi_crg_dev *crg = platform_get_drvdata(pdev);
+
+ hisi_reset_exit(crg->rstc);
+ hisi_clk_remove(pdev);
+}
+EXPORT_SYMBOL_GPL(hisi_crg_remove);
--
2.40.1


2023-07-31 13:48:25

by David Yang

[permalink] [raw]
Subject: [PATCH v6 05/13] clk: hisilicon: hi3519: Use helper functions

Use common helper functions and register clks with a single of_device_id
data.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/clk-hi3519.c | 127 ++++-------------------------
1 file changed, 15 insertions(+), 112 deletions(-)

diff --git a/drivers/clk/hisilicon/clk-hi3519.c b/drivers/clk/hisilicon/clk-hi3519.c
index b871872d9960..cb541de752da 100644
--- a/drivers/clk/hisilicon/clk-hi3519.c
+++ b/drivers/clk/hisilicon/clk-hi3519.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include "clk.h"
-#include "reset.h"
+#include "crg.h"

#define HI3519_INNER_CLK_OFFSET 64
#define HI3519_FIXED_24M 65
@@ -73,130 +73,33 @@ static const struct hisi_gate_clock hi3519_gate_clks[] = {
CLK_SET_RATE_PARENT, 0xe4, 18, 0, },
};

-static struct hisi_clock_data *hi3519_clk_register(struct platform_device *pdev)
-{
- struct hisi_clock_data *clk_data;
- int ret;
-
- clk_data = hisi_clk_alloc(pdev, HI3519_NR_CLKS);
- if (!clk_data)
- return ERR_PTR(-ENOMEM);
-
- ret = hisi_clk_register_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- clk_data);
- if (ret)
- return ERR_PTR(ret);
-
- ret = hisi_clk_register_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- clk_data);
- if (ret)
- goto unregister_fixed_rate;
-
- ret = hisi_clk_register_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_gate_clks),
- clk_data);
- if (ret)
- goto unregister_mux;
-
- ret = of_clk_add_provider(pdev->dev.of_node,
- of_clk_src_onecell_get, &clk_data->clk_data);
- if (ret)
- goto unregister_gate;
-
- return clk_data;
-
-unregister_fixed_rate:
- hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- clk_data);
-
-unregister_mux:
- hisi_clk_unregister_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- clk_data);
-unregister_gate:
- hisi_clk_unregister_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_gate_clks),
- clk_data);
- return ERR_PTR(ret);
-}
-
-static void hi3519_clk_unregister(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
-
- of_clk_del_provider(pdev->dev.of_node);
-
- hisi_clk_unregister_gate(hi3519_gate_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- crg->clk_data);
- hisi_clk_unregister_mux(hi3519_mux_clks,
- ARRAY_SIZE(hi3519_mux_clks),
- crg->clk_data);
- hisi_clk_unregister_fixed_rate(hi3519_fixed_rate_clks,
- ARRAY_SIZE(hi3519_fixed_rate_clks),
- crg->clk_data);
-}
-
-static int hi3519_clk_probe(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg;
-
- crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);
- if (!crg)
- return -ENOMEM;
-
- crg->rstc = hisi_reset_init(pdev);
- if (!crg->rstc)
- return -ENOMEM;
-
- crg->clk_data = hi3519_clk_register(pdev);
- if (IS_ERR(crg->clk_data)) {
- hisi_reset_exit(crg->rstc);
- return PTR_ERR(crg->clk_data);
- }
-
- platform_set_drvdata(pdev, crg);
- return 0;
-}
-
-static void hi3519_clk_remove(struct platform_device *pdev)
-{
- struct hi3519_crg_data *crg = platform_get_drvdata(pdev);
-
- hisi_reset_exit(crg->rstc);
- hi3519_clk_unregister(pdev);
-}
-
+static const struct hisi_clocks hi3519_crg_clks = {
+ .nr = HI3519_NR_CLKS,
+ .fixed_rate_clks = hi3519_fixed_rate_clks,
+ .fixed_rate_clks_num = ARRAY_SIZE(hi3519_fixed_rate_clks),
+ .mux_clks = hi3519_mux_clks,
+ .mux_clks_num = ARRAY_SIZE(hi3519_mux_clks),
+ .gate_clks = hi3519_gate_clks,
+ .gate_clks_num = ARRAY_SIZE(hi3519_gate_clks),
+};

static const struct of_device_id hi3519_clk_match_table[] = {
- { .compatible = "hisilicon,hi3519-crg" },
+ { .compatible = "hisilicon,hi3519-crg",
+ .data = &hi3519_crg_clks },
{ }
};
MODULE_DEVICE_TABLE(of, hi3519_clk_match_table);

static struct platform_driver hi3519_clk_driver = {
- .probe = hi3519_clk_probe,
- .remove_new = hi3519_clk_remove,
+ .probe = hisi_crg_probe,
+ .remove_new = hisi_crg_remove,
.driver = {
.name = "hi3519-clk",
.of_match_table = hi3519_clk_match_table,
},
};

-static int __init hi3519_clk_init(void)
-{
- return platform_driver_register(&hi3519_clk_driver);
-}
-core_initcall(hi3519_clk_init);
-
-static void __exit hi3519_clk_exit(void)
-{
- platform_driver_unregister(&hi3519_clk_driver);
-}
-module_exit(hi3519_clk_exit);
+module_platform_driver(hi3519_clk_driver);

MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("HiSilicon Hi3519 Clock Driver");
--
2.40.1


2023-07-31 14:20:24

by David Yang

[permalink] [raw]
Subject: [PATCH v6 04/13] clk: hisilicon: Remove hisi_crg_funcs

After refactor, no one use hisi_crg_funcs.

Signed-off-by: David Yang <[email protected]>
---
drivers/clk/hisilicon/crg.h | 6 ------
1 file changed, 6 deletions(-)

diff --git a/drivers/clk/hisilicon/crg.h b/drivers/clk/hisilicon/crg.h
index bd8e76b1f6d7..db2324309d41 100644
--- a/drivers/clk/hisilicon/crg.h
+++ b/drivers/clk/hisilicon/crg.h
@@ -11,15 +11,9 @@
struct hisi_clock_data;
struct hisi_reset_controller;

-struct hisi_crg_funcs {
- struct hisi_clock_data* (*register_clks)(struct platform_device *pdev);
- void (*unregister_clks)(struct platform_device *pdev);
-};
-
struct hisi_crg_dev {
struct hisi_clock_data *clk_data;
struct hisi_reset_controller *rstc;
- const struct hisi_crg_funcs *funcs;
};

/* helper functions for platform driver */
--
2.40.1


2023-12-18 06:42:34

by Stephen Boyd

[permalink] [raw]
Subject: Re: [PATCH v6 00/13] clk: hisilicon: Migrate devm APIs

Quoting David Yang (2023-07-31 05:18:00)
> Migrate devm APIs for HiSilicon clock drivers and remove redundant codes.
>
> This series is a partial improvement of [1]
>
> v2: fix test robot error
> v3:
> * size_t for all these num types
> * hisi_clk_unregister() change into separate patch
> * keep relevant header inclusions
> * split driver files changes into separate patches
> * explain hisi_clk_register_fn() checkpatch warnings
> * not fixed: MODULE_LICENSE("GPL v2"), as stated in SPDX-License-Identifier
> * not fixed: "hisilicon,hip04-clock" un-documented, as none of dts files in
> arch/ use it, better to ask hisi people why they pushed this driver
> v4:
> * typo: hisi_clocks_get_nr() should check clks->nr first
> * unexport hisi_clk_unregister_fn() as no one use them outside
> v5: catch up with remove_new refactoring
> v6: fix compilation error and expand macros

This needs to be resent. Sorry. Use mod_devicetable.h instead of
of_device.h please and fix compilation errors.