aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/clk/clk-bulk.c51
-rw-r--r--include/linux/clk.h42
2 files changed, 92 insertions, 1 deletions
diff --git a/drivers/clk/clk-bulk.c b/drivers/clk/clk-bulk.c
index 4460ac52199f..6a7118d4250a 100644
--- a/drivers/clk/clk-bulk.c
+++ b/drivers/clk/clk-bulk.c
@@ -17,9 +17,11 @@
17 */ 17 */
18 18
19#include <linux/clk.h> 19#include <linux/clk.h>
20#include <linux/clk-provider.h>
20#include <linux/device.h> 21#include <linux/device.h>
21#include <linux/export.h> 22#include <linux/export.h>
22#include <linux/of.h> 23#include <linux/of.h>
24#include <linux/slab.h>
23 25
24static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, 26static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
25 struct clk_bulk_data *clks) 27 struct clk_bulk_data *clks)
@@ -49,6 +51,32 @@ err:
49 return ret; 51 return ret;
50} 52}
51 53
54static int __must_check of_clk_bulk_get_all(struct device_node *np,
55 struct clk_bulk_data **clks)
56{
57 struct clk_bulk_data *clk_bulk;
58 int num_clks;
59 int ret;
60
61 num_clks = of_clk_get_parent_count(np);
62 if (!num_clks)
63 return 0;
64
65 clk_bulk = kmalloc_array(num_clks, sizeof(*clk_bulk), GFP_KERNEL);
66 if (!clk_bulk)
67 return -ENOMEM;
68
69 ret = of_clk_bulk_get(np, num_clks, clk_bulk);
70 if (ret) {
71 kfree(clk_bulk);
72 return ret;
73 }
74
75 *clks = clk_bulk;
76
77 return num_clks;
78}
79
52void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) 80void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
53{ 81{
54 while (--num_clks >= 0) { 82 while (--num_clks >= 0) {
@@ -88,6 +116,29 @@ err:
88} 116}
89EXPORT_SYMBOL(clk_bulk_get); 117EXPORT_SYMBOL(clk_bulk_get);
90 118
119void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks)
120{
121 if (IS_ERR_OR_NULL(clks))
122 return;
123
124 clk_bulk_put(num_clks, clks);
125
126 kfree(clks);
127}
128EXPORT_SYMBOL(clk_bulk_put_all);
129
130int __must_check clk_bulk_get_all(struct device *dev,
131 struct clk_bulk_data **clks)
132{
133 struct device_node *np = dev_of_node(dev);
134
135 if (!np)
136 return 0;
137
138 return of_clk_bulk_get_all(np, clks);
139}
140EXPORT_SYMBOL(clk_bulk_get_all);
141
91#ifdef CONFIG_HAVE_CLK_PREPARE 142#ifdef CONFIG_HAVE_CLK_PREPARE
92 143
93/** 144/**
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 4f750c481b82..e9433c76757b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -312,7 +312,26 @@ struct clk *clk_get(struct device *dev, const char *id);
312 */ 312 */
313int __must_check clk_bulk_get(struct device *dev, int num_clks, 313int __must_check clk_bulk_get(struct device *dev, int num_clks,
314 struct clk_bulk_data *clks); 314 struct clk_bulk_data *clks);
315 315/**
316 * clk_bulk_get_all - lookup and obtain all available references to clock
317 * producer.
318 * @dev: device for clock "consumer"
319 * @clks: pointer to the clk_bulk_data table of consumer
320 *
321 * This helper function allows drivers to get all clk consumers in one
322 * operation. If any of the clk cannot be acquired then any clks
323 * that were obtained will be freed before returning to the caller.
324 *
325 * Returns a positive value for the number of clocks obtained while the
326 * clock references are stored in the clk_bulk_data table in @clks field.
327 * Returns 0 if there're none and a negative value if something failed.
328 *
329 * Drivers must assume that the clock source is not enabled.
330 *
331 * clk_bulk_get should not be called from within interrupt context.
332 */
333int __must_check clk_bulk_get_all(struct device *dev,
334 struct clk_bulk_data **clks);
316/** 335/**
317 * devm_clk_bulk_get - managed get multiple clk consumers 336 * devm_clk_bulk_get - managed get multiple clk consumers
318 * @dev: device for clock "consumer" 337 * @dev: device for clock "consumer"
@@ -488,6 +507,19 @@ void clk_put(struct clk *clk);
488void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); 507void clk_bulk_put(int num_clks, struct clk_bulk_data *clks);
489 508
490/** 509/**
510 * clk_bulk_put_all - "free" all the clock source
511 * @num_clks: the number of clk_bulk_data
512 * @clks: the clk_bulk_data table of consumer
513 *
514 * Note: drivers must ensure that all clk_bulk_enable calls made on this
515 * clock source are balanced by clk_bulk_disable calls prior to calling
516 * this function.
517 *
518 * clk_bulk_put_all should not be called from within interrupt context.
519 */
520void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks);
521
522/**
491 * devm_clk_put - "free" a managed clock source 523 * devm_clk_put - "free" a managed clock source
492 * @dev: device used to acquire the clock 524 * @dev: device used to acquire the clock
493 * @clk: clock source acquired with devm_clk_get() 525 * @clk: clock source acquired with devm_clk_get()
@@ -642,6 +674,12 @@ static inline int __must_check clk_bulk_get(struct device *dev, int num_clks,
642 return 0; 674 return 0;
643} 675}
644 676
677static inline int __must_check clk_bulk_get_all(struct device *dev,
678 struct clk_bulk_data **clks)
679{
680 return 0;
681}
682
645static inline struct clk *devm_clk_get(struct device *dev, const char *id) 683static inline struct clk *devm_clk_get(struct device *dev, const char *id)
646{ 684{
647 return NULL; 685 return NULL;
@@ -663,6 +701,8 @@ static inline void clk_put(struct clk *clk) {}
663 701
664static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} 702static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {}
665 703
704static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {}
705
666static inline void devm_clk_put(struct device *dev, struct clk *clk) {} 706static inline void devm_clk_put(struct device *dev, struct clk *clk) {}
667 707
668 708