OSDN Git Service

scsi: iscsi: target: Fix conn_ops double free
[android-x86/kernel.git] / drivers / clk / clk-bulk.c
1 /*
2  * Copyright 2017 NXP
3  *
4  * Dong Aisheng <aisheng.dong@nxp.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms and conditions of the GNU General Public License,
8  * version 2, as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope it will be useful, but WITHOUT
11  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
13  * more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <linux/clk.h>
20 #include <linux/device.h>
21 #include <linux/export.h>
22
23 void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
24 {
25         while (--num_clks >= 0) {
26                 clk_put(clks[num_clks].clk);
27                 clks[num_clks].clk = NULL;
28         }
29 }
30 EXPORT_SYMBOL_GPL(clk_bulk_put);
31
32 int __must_check clk_bulk_get(struct device *dev, int num_clks,
33                               struct clk_bulk_data *clks)
34 {
35         int ret;
36         int i;
37
38         for (i = 0; i < num_clks; i++)
39                 clks[i].clk = NULL;
40
41         for (i = 0; i < num_clks; i++) {
42                 clks[i].clk = clk_get(dev, clks[i].id);
43                 if (IS_ERR(clks[i].clk)) {
44                         ret = PTR_ERR(clks[i].clk);
45                         if (ret != -EPROBE_DEFER)
46                                 dev_err(dev, "Failed to get clk '%s': %d\n",
47                                         clks[i].id, ret);
48                         clks[i].clk = NULL;
49                         goto err;
50                 }
51         }
52
53         return 0;
54
55 err:
56         clk_bulk_put(i, clks);
57
58         return ret;
59 }
60 EXPORT_SYMBOL(clk_bulk_get);
61
62 #ifdef CONFIG_HAVE_CLK_PREPARE
63
64 /**
65  * clk_bulk_unprepare - undo preparation of a set of clock sources
66  * @num_clks: the number of clk_bulk_data
67  * @clks: the clk_bulk_data table being unprepared
68  *
69  * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
70  * Returns 0 on success, -EERROR otherwise.
71  */
72 void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
73 {
74         while (--num_clks >= 0)
75                 clk_unprepare(clks[num_clks].clk);
76 }
77 EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
78
79 /**
80  * clk_bulk_prepare - prepare a set of clocks
81  * @num_clks: the number of clk_bulk_data
82  * @clks: the clk_bulk_data table being prepared
83  *
84  * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
85  * Returns 0 on success, -EERROR otherwise.
86  */
87 int __must_check clk_bulk_prepare(int num_clks,
88                                   const struct clk_bulk_data *clks)
89 {
90         int ret;
91         int i;
92
93         for (i = 0; i < num_clks; i++) {
94                 ret = clk_prepare(clks[i].clk);
95                 if (ret) {
96                         pr_err("Failed to prepare clk '%s': %d\n",
97                                 clks[i].id, ret);
98                         goto err;
99                 }
100         }
101
102         return 0;
103
104 err:
105         clk_bulk_unprepare(i, clks);
106
107         return  ret;
108 }
109 EXPORT_SYMBOL_GPL(clk_bulk_prepare);
110
111 #endif /* CONFIG_HAVE_CLK_PREPARE */
112
113 /**
114  * clk_bulk_disable - gate a set of clocks
115  * @num_clks: the number of clk_bulk_data
116  * @clks: the clk_bulk_data table being gated
117  *
118  * clk_bulk_disable must not sleep, which differentiates it from
119  * clk_bulk_unprepare. clk_bulk_disable must be called before
120  * clk_bulk_unprepare.
121  */
122 void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)
123 {
124
125         while (--num_clks >= 0)
126                 clk_disable(clks[num_clks].clk);
127 }
128 EXPORT_SYMBOL_GPL(clk_bulk_disable);
129
130 /**
131  * clk_bulk_enable - ungate a set of clocks
132  * @num_clks: the number of clk_bulk_data
133  * @clks: the clk_bulk_data table being ungated
134  *
135  * clk_bulk_enable must not sleep
136  * Returns 0 on success, -EERROR otherwise.
137  */
138 int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)
139 {
140         int ret;
141         int i;
142
143         for (i = 0; i < num_clks; i++) {
144                 ret = clk_enable(clks[i].clk);
145                 if (ret) {
146                         pr_err("Failed to enable clk '%s': %d\n",
147                                 clks[i].id, ret);
148                         goto err;
149                 }
150         }
151
152         return 0;
153
154 err:
155         clk_bulk_disable(i, clks);
156
157         return  ret;
158 }
159 EXPORT_SYMBOL_GPL(clk_bulk_enable);