]>
Commit | Line | Data |
---|---|---|
8ef997b6 LPC |
1 | /* |
2 | * This program is free software; you can redistribute it and/or modify | |
3 | * it under the terms of the GNU General Public License version 2 as | |
4 | * published by the Free Software Foundation. | |
5 | */ | |
6 | ||
7 | #include <linux/clk.h> | |
8 | #include <linux/device.h> | |
9 | #include <linux/export.h> | |
10 | #include <linux/gfp.h> | |
11 | ||
12 | static void devm_clk_release(struct device *dev, void *res) | |
13 | { | |
14 | clk_put(*(struct clk **)res); | |
15 | } | |
16 | ||
17 | struct clk *devm_clk_get(struct device *dev, const char *id) | |
18 | { | |
19 | struct clk **ptr, *clk; | |
20 | ||
21 | ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); | |
22 | if (!ptr) | |
23 | return ERR_PTR(-ENOMEM); | |
24 | ||
25 | clk = clk_get(dev, id); | |
26 | if (!IS_ERR(clk)) { | |
27 | *ptr = clk; | |
28 | devres_add(dev, ptr); | |
29 | } else { | |
30 | devres_free(ptr); | |
31 | } | |
32 | ||
33 | return clk; | |
34 | } | |
35 | EXPORT_SYMBOL(devm_clk_get); | |
36 | ||
618aee02 DA |
37 | struct clk_bulk_devres { |
38 | struct clk_bulk_data *clks; | |
39 | int num_clks; | |
40 | }; | |
41 | ||
42 | static void devm_clk_bulk_release(struct device *dev, void *res) | |
43 | { | |
44 | struct clk_bulk_devres *devres = res; | |
45 | ||
46 | clk_bulk_put(devres->num_clks, devres->clks); | |
47 | } | |
48 | ||
49 | int __must_check devm_clk_bulk_get(struct device *dev, int num_clks, | |
50 | struct clk_bulk_data *clks) | |
51 | { | |
52 | struct clk_bulk_devres *devres; | |
53 | int ret; | |
54 | ||
55 | devres = devres_alloc(devm_clk_bulk_release, | |
56 | sizeof(*devres), GFP_KERNEL); | |
57 | if (!devres) | |
58 | return -ENOMEM; | |
59 | ||
60 | ret = clk_bulk_get(dev, num_clks, clks); | |
61 | if (!ret) { | |
62 | devres->clks = clks; | |
63 | devres->num_clks = num_clks; | |
64 | devres_add(dev, devres); | |
65 | } else { | |
66 | devres_free(devres); | |
67 | } | |
68 | ||
69 | return ret; | |
70 | } | |
71 | EXPORT_SYMBOL_GPL(devm_clk_bulk_get); | |
72 | ||
f08c2e28 DA |
73 | int __must_check devm_clk_bulk_get_all(struct device *dev, |
74 | struct clk_bulk_data **clks) | |
75 | { | |
76 | struct clk_bulk_devres *devres; | |
77 | int ret; | |
78 | ||
79 | devres = devres_alloc(devm_clk_bulk_release, | |
80 | sizeof(*devres), GFP_KERNEL); | |
81 | if (!devres) | |
82 | return -ENOMEM; | |
83 | ||
84 | ret = clk_bulk_get_all(dev, &devres->clks); | |
85 | if (ret > 0) { | |
86 | *clks = devres->clks; | |
87 | devres->num_clks = ret; | |
88 | devres_add(dev, devres); | |
89 | } else { | |
90 | devres_free(devres); | |
91 | } | |
92 | ||
93 | return ret; | |
94 | } | |
95 | EXPORT_SYMBOL_GPL(devm_clk_bulk_get_all); | |
96 | ||
8ef997b6 LPC |
97 | static int devm_clk_match(struct device *dev, void *res, void *data) |
98 | { | |
99 | struct clk **c = res; | |
100 | if (!c || !*c) { | |
101 | WARN_ON(!c || !*c); | |
102 | return 0; | |
103 | } | |
104 | return *c == data; | |
105 | } | |
106 | ||
107 | void devm_clk_put(struct device *dev, struct clk *clk) | |
108 | { | |
109 | int ret; | |
110 | ||
20332ff3 | 111 | ret = devres_release(dev, devm_clk_release, devm_clk_match, clk); |
8ef997b6 LPC |
112 | |
113 | WARN_ON(ret); | |
114 | } | |
115 | EXPORT_SYMBOL(devm_clk_put); | |
71a2f115 KM |
116 | |
117 | struct clk *devm_get_clk_from_child(struct device *dev, | |
118 | struct device_node *np, const char *con_id) | |
119 | { | |
120 | struct clk **ptr, *clk; | |
121 | ||
122 | ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL); | |
123 | if (!ptr) | |
124 | return ERR_PTR(-ENOMEM); | |
125 | ||
126 | clk = of_clk_get_by_name(np, con_id); | |
127 | if (!IS_ERR(clk)) { | |
128 | *ptr = clk; | |
129 | devres_add(dev, ptr); | |
130 | } else { | |
131 | devres_free(ptr); | |
132 | } | |
133 | ||
134 | return clk; | |
135 | } | |
136 | EXPORT_SYMBOL(devm_get_clk_from_child); |