blob: 4460ac52199fb93f5a1513e1c0a6b71a3a318625 [file] [log] [blame]
Dong Aisheng266e4e92017-05-19 21:49:04 +08001/*
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>
Dong Aishengcfdc0412018-08-31 12:45:53 +080022#include <linux/of.h>
23
24static int __must_check of_clk_bulk_get(struct device_node *np, int num_clks,
25 struct clk_bulk_data *clks)
26{
27 int ret;
28 int i;
29
30 for (i = 0; i < num_clks; i++)
31 clks[i].clk = NULL;
32
33 for (i = 0; i < num_clks; i++) {
34 clks[i].clk = of_clk_get(np, i);
35 if (IS_ERR(clks[i].clk)) {
36 ret = PTR_ERR(clks[i].clk);
37 pr_err("%pOF: Failed to get clk index: %d ret: %d\n",
38 np, i, ret);
39 clks[i].clk = NULL;
40 goto err;
41 }
42 }
43
44 return 0;
45
46err:
47 clk_bulk_put(i, clks);
48
49 return ret;
50}
Dong Aisheng266e4e92017-05-19 21:49:04 +080051
52void clk_bulk_put(int num_clks, struct clk_bulk_data *clks)
53{
54 while (--num_clks >= 0) {
55 clk_put(clks[num_clks].clk);
56 clks[num_clks].clk = NULL;
57 }
58}
59EXPORT_SYMBOL_GPL(clk_bulk_put);
60
61int __must_check clk_bulk_get(struct device *dev, int num_clks,
62 struct clk_bulk_data *clks)
63{
64 int ret;
65 int i;
66
67 for (i = 0; i < num_clks; i++)
68 clks[i].clk = NULL;
69
70 for (i = 0; i < num_clks; i++) {
71 clks[i].clk = clk_get(dev, clks[i].id);
72 if (IS_ERR(clks[i].clk)) {
73 ret = PTR_ERR(clks[i].clk);
Jerome Brunet329470f2018-04-09 16:13:03 +020074 if (ret != -EPROBE_DEFER)
75 dev_err(dev, "Failed to get clk '%s': %d\n",
76 clks[i].id, ret);
Dong Aisheng266e4e92017-05-19 21:49:04 +080077 clks[i].clk = NULL;
78 goto err;
79 }
80 }
81
82 return 0;
83
84err:
85 clk_bulk_put(i, clks);
86
87 return ret;
88}
89EXPORT_SYMBOL(clk_bulk_get);
90
91#ifdef CONFIG_HAVE_CLK_PREPARE
92
93/**
94 * clk_bulk_unprepare - undo preparation of a set of clock sources
95 * @num_clks: the number of clk_bulk_data
96 * @clks: the clk_bulk_data table being unprepared
97 *
98 * clk_bulk_unprepare may sleep, which differentiates it from clk_bulk_disable.
99 * Returns 0 on success, -EERROR otherwise.
100 */
101void clk_bulk_unprepare(int num_clks, const struct clk_bulk_data *clks)
102{
103 while (--num_clks >= 0)
104 clk_unprepare(clks[num_clks].clk);
105}
106EXPORT_SYMBOL_GPL(clk_bulk_unprepare);
107
108/**
109 * clk_bulk_prepare - prepare a set of clocks
110 * @num_clks: the number of clk_bulk_data
111 * @clks: the clk_bulk_data table being prepared
112 *
113 * clk_bulk_prepare may sleep, which differentiates it from clk_bulk_enable.
114 * Returns 0 on success, -EERROR otherwise.
115 */
116int __must_check clk_bulk_prepare(int num_clks,
117 const struct clk_bulk_data *clks)
118{
119 int ret;
120 int i;
121
122 for (i = 0; i < num_clks; i++) {
123 ret = clk_prepare(clks[i].clk);
124 if (ret) {
125 pr_err("Failed to prepare clk '%s': %d\n",
126 clks[i].id, ret);
127 goto err;
128 }
129 }
130
131 return 0;
132
133err:
134 clk_bulk_unprepare(i, clks);
135
136 return ret;
137}
Bjorn Andersson9792bf52017-09-22 22:00:29 -0700138EXPORT_SYMBOL_GPL(clk_bulk_prepare);
Dong Aisheng266e4e92017-05-19 21:49:04 +0800139
140#endif /* CONFIG_HAVE_CLK_PREPARE */
141
142/**
143 * clk_bulk_disable - gate a set of clocks
144 * @num_clks: the number of clk_bulk_data
145 * @clks: the clk_bulk_data table being gated
146 *
147 * clk_bulk_disable must not sleep, which differentiates it from
148 * clk_bulk_unprepare. clk_bulk_disable must be called before
149 * clk_bulk_unprepare.
150 */
151void clk_bulk_disable(int num_clks, const struct clk_bulk_data *clks)
152{
153
154 while (--num_clks >= 0)
155 clk_disable(clks[num_clks].clk);
156}
157EXPORT_SYMBOL_GPL(clk_bulk_disable);
158
159/**
160 * clk_bulk_enable - ungate a set of clocks
161 * @num_clks: the number of clk_bulk_data
162 * @clks: the clk_bulk_data table being ungated
163 *
164 * clk_bulk_enable must not sleep
165 * Returns 0 on success, -EERROR otherwise.
166 */
167int __must_check clk_bulk_enable(int num_clks, const struct clk_bulk_data *clks)
168{
169 int ret;
170 int i;
171
172 for (i = 0; i < num_clks; i++) {
173 ret = clk_enable(clks[i].clk);
174 if (ret) {
175 pr_err("Failed to enable clk '%s': %d\n",
176 clks[i].id, ret);
177 goto err;
178 }
179 }
180
181 return 0;
182
183err:
184 clk_bulk_disable(i, clks);
185
186 return ret;
187}
188EXPORT_SYMBOL_GPL(clk_bulk_enable);