treewide: Replace GPLv2 boilerplate/reference with SPDX - rule 174
[sfrench/cifs-2.6.git] / drivers / clk / mediatek / clk-mtk.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (c) 2014 MediaTek Inc.
4  * Author: James Liao <jamesjj.liao@mediatek.com>
5  */
6
7 #include <linux/of.h>
8 #include <linux/of_address.h>
9 #include <linux/err.h>
10 #include <linux/io.h>
11 #include <linux/slab.h>
12 #include <linux/delay.h>
13 #include <linux/clkdev.h>
14 #include <linux/mfd/syscon.h>
15
16 #include "clk-mtk.h"
17 #include "clk-gate.h"
18
19 struct clk_onecell_data *mtk_alloc_clk_data(unsigned int clk_num)
20 {
21         int i;
22         struct clk_onecell_data *clk_data;
23
24         clk_data = kzalloc(sizeof(*clk_data), GFP_KERNEL);
25         if (!clk_data)
26                 return NULL;
27
28         clk_data->clks = kcalloc(clk_num, sizeof(*clk_data->clks), GFP_KERNEL);
29         if (!clk_data->clks)
30                 goto err_out;
31
32         clk_data->clk_num = clk_num;
33
34         for (i = 0; i < clk_num; i++)
35                 clk_data->clks[i] = ERR_PTR(-ENOENT);
36
37         return clk_data;
38 err_out:
39         kfree(clk_data);
40
41         return NULL;
42 }
43
44 void mtk_clk_register_fixed_clks(const struct mtk_fixed_clk *clks,
45                 int num, struct clk_onecell_data *clk_data)
46 {
47         int i;
48         struct clk *clk;
49
50         for (i = 0; i < num; i++) {
51                 const struct mtk_fixed_clk *rc = &clks[i];
52
53                 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[rc->id]))
54                         continue;
55
56                 clk = clk_register_fixed_rate(NULL, rc->name, rc->parent, 0,
57                                               rc->rate);
58
59                 if (IS_ERR(clk)) {
60                         pr_err("Failed to register clk %s: %ld\n",
61                                         rc->name, PTR_ERR(clk));
62                         continue;
63                 }
64
65                 if (clk_data)
66                         clk_data->clks[rc->id] = clk;
67         }
68 }
69
70 void mtk_clk_register_factors(const struct mtk_fixed_factor *clks,
71                 int num, struct clk_onecell_data *clk_data)
72 {
73         int i;
74         struct clk *clk;
75
76         for (i = 0; i < num; i++) {
77                 const struct mtk_fixed_factor *ff = &clks[i];
78
79                 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[ff->id]))
80                         continue;
81
82                 clk = clk_register_fixed_factor(NULL, ff->name, ff->parent_name,
83                                 CLK_SET_RATE_PARENT, ff->mult, ff->div);
84
85                 if (IS_ERR(clk)) {
86                         pr_err("Failed to register clk %s: %ld\n",
87                                         ff->name, PTR_ERR(clk));
88                         continue;
89                 }
90
91                 if (clk_data)
92                         clk_data->clks[ff->id] = clk;
93         }
94 }
95
96 int mtk_clk_register_gates(struct device_node *node,
97                 const struct mtk_gate *clks,
98                 int num, struct clk_onecell_data *clk_data)
99 {
100         int i;
101         struct clk *clk;
102         struct regmap *regmap;
103
104         if (!clk_data)
105                 return -ENOMEM;
106
107         regmap = syscon_node_to_regmap(node);
108         if (IS_ERR(regmap)) {
109                 pr_err("Cannot find regmap for %pOF: %ld\n", node,
110                                 PTR_ERR(regmap));
111                 return PTR_ERR(regmap);
112         }
113
114         for (i = 0; i < num; i++) {
115                 const struct mtk_gate *gate = &clks[i];
116
117                 if (!IS_ERR_OR_NULL(clk_data->clks[gate->id]))
118                         continue;
119
120                 clk = mtk_clk_register_gate(gate->name, gate->parent_name,
121                                 regmap,
122                                 gate->regs->set_ofs,
123                                 gate->regs->clr_ofs,
124                                 gate->regs->sta_ofs,
125                                 gate->shift, gate->ops, gate->flags);
126
127                 if (IS_ERR(clk)) {
128                         pr_err("Failed to register clk %s: %ld\n",
129                                         gate->name, PTR_ERR(clk));
130                         continue;
131                 }
132
133                 clk_data->clks[gate->id] = clk;
134         }
135
136         return 0;
137 }
138
139 struct clk *mtk_clk_register_composite(const struct mtk_composite *mc,
140                 void __iomem *base, spinlock_t *lock)
141 {
142         struct clk *clk;
143         struct clk_mux *mux = NULL;
144         struct clk_gate *gate = NULL;
145         struct clk_divider *div = NULL;
146         struct clk_hw *mux_hw = NULL, *gate_hw = NULL, *div_hw = NULL;
147         const struct clk_ops *mux_ops = NULL, *gate_ops = NULL, *div_ops = NULL;
148         const char * const *parent_names;
149         const char *parent;
150         int num_parents;
151         int ret;
152
153         if (mc->mux_shift >= 0) {
154                 mux = kzalloc(sizeof(*mux), GFP_KERNEL);
155                 if (!mux)
156                         return ERR_PTR(-ENOMEM);
157
158                 mux->reg = base + mc->mux_reg;
159                 mux->mask = BIT(mc->mux_width) - 1;
160                 mux->shift = mc->mux_shift;
161                 mux->lock = lock;
162                 mux->flags = mc->mux_flags;
163                 mux_hw = &mux->hw;
164                 mux_ops = &clk_mux_ops;
165
166                 parent_names = mc->parent_names;
167                 num_parents = mc->num_parents;
168         } else {
169                 parent = mc->parent;
170                 parent_names = &parent;
171                 num_parents = 1;
172         }
173
174         if (mc->gate_shift >= 0) {
175                 gate = kzalloc(sizeof(*gate), GFP_KERNEL);
176                 if (!gate) {
177                         ret = -ENOMEM;
178                         goto err_out;
179                 }
180
181                 gate->reg = base + mc->gate_reg;
182                 gate->bit_idx = mc->gate_shift;
183                 gate->flags = CLK_GATE_SET_TO_DISABLE;
184                 gate->lock = lock;
185
186                 gate_hw = &gate->hw;
187                 gate_ops = &clk_gate_ops;
188         }
189
190         if (mc->divider_shift >= 0) {
191                 div = kzalloc(sizeof(*div), GFP_KERNEL);
192                 if (!div) {
193                         ret = -ENOMEM;
194                         goto err_out;
195                 }
196
197                 div->reg = base + mc->divider_reg;
198                 div->shift = mc->divider_shift;
199                 div->width = mc->divider_width;
200                 div->lock = lock;
201
202                 div_hw = &div->hw;
203                 div_ops = &clk_divider_ops;
204         }
205
206         clk = clk_register_composite(NULL, mc->name, parent_names, num_parents,
207                 mux_hw, mux_ops,
208                 div_hw, div_ops,
209                 gate_hw, gate_ops,
210                 mc->flags);
211
212         if (IS_ERR(clk)) {
213                 ret = PTR_ERR(clk);
214                 goto err_out;
215         }
216
217         return clk;
218 err_out:
219         kfree(div);
220         kfree(gate);
221         kfree(mux);
222
223         return ERR_PTR(ret);
224 }
225
226 void mtk_clk_register_composites(const struct mtk_composite *mcs,
227                 int num, void __iomem *base, spinlock_t *lock,
228                 struct clk_onecell_data *clk_data)
229 {
230         struct clk *clk;
231         int i;
232
233         for (i = 0; i < num; i++) {
234                 const struct mtk_composite *mc = &mcs[i];
235
236                 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mc->id]))
237                         continue;
238
239                 clk = mtk_clk_register_composite(mc, base, lock);
240
241                 if (IS_ERR(clk)) {
242                         pr_err("Failed to register clk %s: %ld\n",
243                                         mc->name, PTR_ERR(clk));
244                         continue;
245                 }
246
247                 if (clk_data)
248                         clk_data->clks[mc->id] = clk;
249         }
250 }
251
252 void mtk_clk_register_dividers(const struct mtk_clk_divider *mcds,
253                         int num, void __iomem *base, spinlock_t *lock,
254                                 struct clk_onecell_data *clk_data)
255 {
256         struct clk *clk;
257         int i;
258
259         for (i = 0; i <  num; i++) {
260                 const struct mtk_clk_divider *mcd = &mcds[i];
261
262                 if (clk_data && !IS_ERR_OR_NULL(clk_data->clks[mcd->id]))
263                         continue;
264
265                 clk = clk_register_divider(NULL, mcd->name, mcd->parent_name,
266                         mcd->flags, base +  mcd->div_reg, mcd->div_shift,
267                         mcd->div_width, mcd->clk_divider_flags, lock);
268
269                 if (IS_ERR(clk)) {
270                         pr_err("Failed to register clk %s: %ld\n",
271                                 mcd->name, PTR_ERR(clk));
272                         continue;
273                 }
274
275                 if (clk_data)
276                         clk_data->clks[mcd->id] = clk;
277         }
278 }