ab61f0b6580fec5c09a7cdbd02ae49977f33029b
[openwrt/staging/stintel.git] /
1 From 265b07df758a998f60cf5b5aec6bd72ca676655e Mon Sep 17 00:00:00 2001
2 From: Shradha Todi <shradha.t@samsung.com>
3 Date: Tue, 20 Feb 2024 14:10:45 +0530
4 Subject: [PATCH] clk: Provide managed helper to get and enable bulk clocks
5
6 Provide a managed devm_clk_bulk* wrapper to get and enable all
7 bulk clocks in order to simplify drivers that keeps all clocks
8 enabled for the time of driver operation.
9
10 Suggested-by: Marek Szyprowski <m.szyprowski@samsung.com>
11 Reviewed-by: Alim Akhtar <alim.akhtar@samsung.com>
12 Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
13 Signed-off-by: Shradha Todi <shradha.t@samsung.com>
14 Link: https://lore.kernel.org/r/20240220084046.23786-2-shradha.t@samsung.com
15 Signed-off-by: Stephen Boyd <sboyd@kernel.org>
16 ---
17 drivers/clk/clk-devres.c | 40 ++++++++++++++++++++++++++++++++++++++++
18 include/linux/clk.h | 22 ++++++++++++++++++++++
19 2 files changed, 62 insertions(+)
20
21 diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
22 index 737aa70e2cb3..90e6078fb6e1 100644
23 --- a/drivers/clk/clk-devres.c
24 +++ b/drivers/clk/clk-devres.c
25 @@ -182,6 +182,46 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
26 }
27 EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all);
28
29 +static void devm_clk_bulk_release_all_enable(struct device *dev, void *res)
30 +{
31 + struct clk_bulk_devres *devres = res;
32 +
33 + clk_bulk_disable_unprepare(devres->num_clks, devres->clks);
34 + clk_bulk_put_all(devres->num_clks, devres->clks);
35 +}
36 +
37 +int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
38 + struct clk_bulk_data **clks)
39 +{
40 + struct clk_bulk_devres *devres;
41 + int ret;
42 +
43 + devres = devres_alloc(devm_clk_bulk_release_all_enable,
44 + sizeof(*devres), GFP_KERNEL);
45 + if (!devres)
46 + return -ENOMEM;
47 +
48 + ret = clk_bulk_get_all(dev, &devres->clks);
49 + if (ret > 0) {
50 + *clks = devres->clks;
51 + devres->num_clks = ret;
52 + } else {
53 + devres_free(devres);
54 + return ret;
55 + }
56 +
57 + ret = clk_bulk_prepare_enable(devres->num_clks, *clks);
58 + if (!ret) {
59 + devres_add(dev, devres);
60 + } else {
61 + clk_bulk_put_all(devres->num_clks, devres->clks);
62 + devres_free(devres);
63 + }
64 +
65 + return ret;
66 +}
67 +EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all_enable);
68 +
69 static int devm_clk_match(struct device *dev, void *res, void *data)
70 {
71 struct clk **c = res;
72 diff --git a/include/linux/clk.h b/include/linux/clk.h
73 index 06f1b292f8a0..0f44d3863de2 100644
74 --- a/include/linux/clk.h
75 +++ b/include/linux/clk.h
76 @@ -478,6 +478,22 @@ int __must_check devm_clk_bulk_get_optional(struct device *dev, int num_clks,
77 int __must_check devm_clk_bulk_get_all(struct device *dev,
78 struct clk_bulk_data **clks);
79
80 +/**
81 + * devm_clk_bulk_get_all_enable - Get and enable all clocks of the consumer (managed)
82 + * @dev: device for clock "consumer"
83 + * @clks: pointer to the clk_bulk_data table of consumer
84 + *
85 + * Returns success (0) or negative errno.
86 + *
87 + * This helper function allows drivers to get all clocks of the
88 + * consumer and enables them in one operation with management.
89 + * The clks will automatically be disabled and freed when the device
90 + * is unbound.
91 + */
92 +
93 +int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
94 + struct clk_bulk_data **clks);
95 +
96 /**
97 * devm_clk_get - lookup and obtain a managed reference to a clock producer.
98 * @dev: device for clock "consumer"
99 @@ -968,6 +984,12 @@ static inline int __must_check devm_clk_bulk_get_all(struct device *dev,
100 return 0;
101 }
102
103 +static inline int __must_check devm_clk_bulk_get_all_enable(struct device *dev,
104 + struct clk_bulk_data **clks)
105 +{
106 + return 0;
107 +}
108 +
109 static inline struct clk *devm_get_clk_from_child(struct device *dev,
110 struct device_node *np, const char *con_id)
111 {
112 --
113 2.45.2
114