diff options
-rw-r--r-- | drivers/clk/clk-bulk.c | 51 | ||||
-rw-r--r-- | include/linux/clk.h | 42 |
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 | ||
24 | static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks, | 26 | static 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 | ||
54 | static 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 | |||
52 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) | 80 | void 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 | } |
89 | EXPORT_SYMBOL(clk_bulk_get); | 117 | EXPORT_SYMBOL(clk_bulk_get); |
90 | 118 | ||
119 | void 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 | } | ||
128 | EXPORT_SYMBOL(clk_bulk_put_all); | ||
129 | |||
130 | int __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 | } | ||
140 | EXPORT_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 | */ |
313 | int __must_check clk_bulk_get(struct device *dev, int num_clks, | 313 | int __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 | */ | ||
333 | int __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); | |||
488 | void clk_bulk_put(int num_clks, struct clk_bulk_data *clks); | 507 | void 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 | */ | ||
520 | void 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 | ||
677 | static inline int __must_check clk_bulk_get_all(struct device *dev, | ||
678 | struct clk_bulk_data **clks) | ||
679 | { | ||
680 | return 0; | ||
681 | } | ||
682 | |||
645 | static inline struct clk *devm_clk_get(struct device *dev, const char *id) | 683 | static 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 | ||
664 | static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} | 702 | static inline void clk_bulk_put(int num_clks, struct clk_bulk_data *clks) {} |
665 | 703 | ||
704 | static inline void clk_bulk_put_all(int num_clks, struct clk_bulk_data *clks) {} | ||
705 | |||
666 | static inline void devm_clk_put(struct device *dev, struct clk *clk) {} | 706 | static inline void devm_clk_put(struct device *dev, struct clk *clk) {} |
667 | 707 | ||
668 | 708 | ||