clk: rockchip: rk3328: add pclk for acodec
[firefly-linux-kernel-4.4.55.git] / drivers / clk / at91 / clk-peripheral.c
1 /*
2  *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  */
10
11 #include <linux/clk-provider.h>
12 #include <linux/clkdev.h>
13 #include <linux/clk/at91_pmc.h>
14 #include <linux/of.h>
15 #include <linux/of_address.h>
16 #include <linux/io.h>
17
18 #include "pmc.h"
19
20 #define PERIPHERAL_MAX          64
21
22 #define PERIPHERAL_AT91RM9200   0
23 #define PERIPHERAL_AT91SAM9X5   1
24
25 #define PERIPHERAL_ID_MIN       2
26 #define PERIPHERAL_ID_MAX       31
27 #define PERIPHERAL_MASK(id)     (1 << ((id) & PERIPHERAL_ID_MAX))
28
29 #define PERIPHERAL_RSHIFT_MASK  0x3
30 #define PERIPHERAL_RSHIFT(val)  (((val) >> 16) & PERIPHERAL_RSHIFT_MASK)
31
32 #define PERIPHERAL_MAX_SHIFT    3
33
34 struct clk_peripheral {
35         struct clk_hw hw;
36         struct at91_pmc *pmc;
37         u32 id;
38 };
39
40 #define to_clk_peripheral(hw) container_of(hw, struct clk_peripheral, hw)
41
42 struct clk_sam9x5_peripheral {
43         struct clk_hw hw;
44         struct at91_pmc *pmc;
45         struct clk_range range;
46         u32 id;
47         u32 div;
48         bool auto_div;
49 };
50
51 #define to_clk_sam9x5_peripheral(hw) \
52         container_of(hw, struct clk_sam9x5_peripheral, hw)
53
54 static int clk_peripheral_enable(struct clk_hw *hw)
55 {
56         struct clk_peripheral *periph = to_clk_peripheral(hw);
57         struct at91_pmc *pmc = periph->pmc;
58         int offset = AT91_PMC_PCER;
59         u32 id = periph->id;
60
61         if (id < PERIPHERAL_ID_MIN)
62                 return 0;
63         if (id > PERIPHERAL_ID_MAX)
64                 offset = AT91_PMC_PCER1;
65         pmc_write(pmc, offset, PERIPHERAL_MASK(id));
66         return 0;
67 }
68
69 static void clk_peripheral_disable(struct clk_hw *hw)
70 {
71         struct clk_peripheral *periph = to_clk_peripheral(hw);
72         struct at91_pmc *pmc = periph->pmc;
73         int offset = AT91_PMC_PCDR;
74         u32 id = periph->id;
75
76         if (id < PERIPHERAL_ID_MIN)
77                 return;
78         if (id > PERIPHERAL_ID_MAX)
79                 offset = AT91_PMC_PCDR1;
80         pmc_write(pmc, offset, PERIPHERAL_MASK(id));
81 }
82
83 static int clk_peripheral_is_enabled(struct clk_hw *hw)
84 {
85         struct clk_peripheral *periph = to_clk_peripheral(hw);
86         struct at91_pmc *pmc = periph->pmc;
87         int offset = AT91_PMC_PCSR;
88         u32 id = periph->id;
89
90         if (id < PERIPHERAL_ID_MIN)
91                 return 1;
92         if (id > PERIPHERAL_ID_MAX)
93                 offset = AT91_PMC_PCSR1;
94         return !!(pmc_read(pmc, offset) & PERIPHERAL_MASK(id));
95 }
96
97 static const struct clk_ops peripheral_ops = {
98         .enable = clk_peripheral_enable,
99         .disable = clk_peripheral_disable,
100         .is_enabled = clk_peripheral_is_enabled,
101 };
102
103 static struct clk * __init
104 at91_clk_register_peripheral(struct at91_pmc *pmc, const char *name,
105                              const char *parent_name, u32 id)
106 {
107         struct clk_peripheral *periph;
108         struct clk *clk = NULL;
109         struct clk_init_data init;
110
111         if (!pmc || !name || !parent_name || id > PERIPHERAL_ID_MAX)
112                 return ERR_PTR(-EINVAL);
113
114         periph = kzalloc(sizeof(*periph), GFP_KERNEL);
115         if (!periph)
116                 return ERR_PTR(-ENOMEM);
117
118         init.name = name;
119         init.ops = &peripheral_ops;
120         init.parent_names = (parent_name ? &parent_name : NULL);
121         init.num_parents = (parent_name ? 1 : 0);
122         init.flags = 0;
123
124         periph->id = id;
125         periph->hw.init = &init;
126         periph->pmc = pmc;
127
128         clk = clk_register(NULL, &periph->hw);
129         if (IS_ERR(clk))
130                 kfree(periph);
131
132         return clk;
133 }
134
135 static void clk_sam9x5_peripheral_autodiv(struct clk_sam9x5_peripheral *periph)
136 {
137         struct clk_hw *parent;
138         unsigned long parent_rate;
139         int shift = 0;
140
141         if (!periph->auto_div)
142                 return;
143
144         if (periph->range.max) {
145                 parent = clk_hw_get_parent_by_index(&periph->hw, 0);
146                 parent_rate = clk_hw_get_rate(parent);
147                 if (!parent_rate)
148                         return;
149
150                 for (; shift < PERIPHERAL_MAX_SHIFT; shift++) {
151                         if (parent_rate >> shift <= periph->range.max)
152                                 break;
153                 }
154         }
155
156         periph->auto_div = false;
157         periph->div = shift;
158 }
159
160 static int clk_sam9x5_peripheral_enable(struct clk_hw *hw)
161 {
162         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
163         struct at91_pmc *pmc = periph->pmc;
164         u32 tmp;
165
166         if (periph->id < PERIPHERAL_ID_MIN)
167                 return 0;
168
169         pmc_lock(pmc);
170         pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
171         tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_DIV_MASK;
172         pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_DIV(periph->div)
173                                          | AT91_PMC_PCR_CMD
174                                          | AT91_PMC_PCR_EN);
175         pmc_unlock(pmc);
176         return 0;
177 }
178
179 static void clk_sam9x5_peripheral_disable(struct clk_hw *hw)
180 {
181         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
182         struct at91_pmc *pmc = periph->pmc;
183         u32 tmp;
184
185         if (periph->id < PERIPHERAL_ID_MIN)
186                 return;
187
188         pmc_lock(pmc);
189         pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
190         tmp = pmc_read(pmc, AT91_PMC_PCR) & ~AT91_PMC_PCR_EN;
191         pmc_write(pmc, AT91_PMC_PCR, tmp | AT91_PMC_PCR_CMD);
192         pmc_unlock(pmc);
193 }
194
195 static int clk_sam9x5_peripheral_is_enabled(struct clk_hw *hw)
196 {
197         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
198         struct at91_pmc *pmc = periph->pmc;
199         int ret;
200
201         if (periph->id < PERIPHERAL_ID_MIN)
202                 return 1;
203
204         pmc_lock(pmc);
205         pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
206         ret = !!(pmc_read(pmc, AT91_PMC_PCR) & AT91_PMC_PCR_EN);
207         pmc_unlock(pmc);
208
209         return ret;
210 }
211
212 static unsigned long
213 clk_sam9x5_peripheral_recalc_rate(struct clk_hw *hw,
214                                   unsigned long parent_rate)
215 {
216         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
217         struct at91_pmc *pmc = periph->pmc;
218         u32 tmp;
219
220         if (periph->id < PERIPHERAL_ID_MIN)
221                 return parent_rate;
222
223         pmc_lock(pmc);
224         pmc_write(pmc, AT91_PMC_PCR, (periph->id & AT91_PMC_PCR_PID_MASK));
225         tmp = pmc_read(pmc, AT91_PMC_PCR);
226         pmc_unlock(pmc);
227
228         if (tmp & AT91_PMC_PCR_EN) {
229                 periph->div = PERIPHERAL_RSHIFT(tmp);
230                 periph->auto_div = false;
231         } else {
232                 clk_sam9x5_peripheral_autodiv(periph);
233         }
234
235         return parent_rate >> periph->div;
236 }
237
238 static long clk_sam9x5_peripheral_round_rate(struct clk_hw *hw,
239                                              unsigned long rate,
240                                              unsigned long *parent_rate)
241 {
242         int shift = 0;
243         unsigned long best_rate;
244         unsigned long best_diff;
245         unsigned long cur_rate = *parent_rate;
246         unsigned long cur_diff;
247         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
248
249         if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max)
250                 return *parent_rate;
251
252         if (periph->range.max) {
253                 for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
254                         cur_rate = *parent_rate >> shift;
255                         if (cur_rate <= periph->range.max)
256                                 break;
257                 }
258         }
259
260         if (rate >= cur_rate)
261                 return cur_rate;
262
263         best_diff = cur_rate - rate;
264         best_rate = cur_rate;
265         for (; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
266                 cur_rate = *parent_rate >> shift;
267                 if (cur_rate < rate)
268                         cur_diff = rate - cur_rate;
269                 else
270                         cur_diff = cur_rate - rate;
271
272                 if (cur_diff < best_diff) {
273                         best_diff = cur_diff;
274                         best_rate = cur_rate;
275                 }
276
277                 if (!best_diff || cur_rate < rate)
278                         break;
279         }
280
281         return best_rate;
282 }
283
284 static int clk_sam9x5_peripheral_set_rate(struct clk_hw *hw,
285                                           unsigned long rate,
286                                           unsigned long parent_rate)
287 {
288         int shift;
289         struct clk_sam9x5_peripheral *periph = to_clk_sam9x5_peripheral(hw);
290         if (periph->id < PERIPHERAL_ID_MIN || !periph->range.max) {
291                 if (parent_rate == rate)
292                         return 0;
293                 else
294                         return -EINVAL;
295         }
296
297         if (periph->range.max && rate > periph->range.max)
298                 return -EINVAL;
299
300         for (shift = 0; shift <= PERIPHERAL_MAX_SHIFT; shift++) {
301                 if (parent_rate >> shift == rate) {
302                         periph->auto_div = false;
303                         periph->div = shift;
304                         return 0;
305                 }
306         }
307
308         return -EINVAL;
309 }
310
311 static const struct clk_ops sam9x5_peripheral_ops = {
312         .enable = clk_sam9x5_peripheral_enable,
313         .disable = clk_sam9x5_peripheral_disable,
314         .is_enabled = clk_sam9x5_peripheral_is_enabled,
315         .recalc_rate = clk_sam9x5_peripheral_recalc_rate,
316         .round_rate = clk_sam9x5_peripheral_round_rate,
317         .set_rate = clk_sam9x5_peripheral_set_rate,
318 };
319
320 static struct clk * __init
321 at91_clk_register_sam9x5_peripheral(struct at91_pmc *pmc, const char *name,
322                                     const char *parent_name, u32 id,
323                                     const struct clk_range *range)
324 {
325         struct clk_sam9x5_peripheral *periph;
326         struct clk *clk = NULL;
327         struct clk_init_data init;
328
329         if (!pmc || !name || !parent_name)
330                 return ERR_PTR(-EINVAL);
331
332         periph = kzalloc(sizeof(*periph), GFP_KERNEL);
333         if (!periph)
334                 return ERR_PTR(-ENOMEM);
335
336         init.name = name;
337         init.ops = &sam9x5_peripheral_ops;
338         init.parent_names = (parent_name ? &parent_name : NULL);
339         init.num_parents = (parent_name ? 1 : 0);
340         init.flags = 0;
341
342         periph->id = id;
343         periph->hw.init = &init;
344         periph->div = 0;
345         periph->pmc = pmc;
346         periph->auto_div = true;
347         periph->range = *range;
348
349         clk = clk_register(NULL, &periph->hw);
350         if (IS_ERR(clk))
351                 kfree(periph);
352         else
353                 clk_sam9x5_peripheral_autodiv(periph);
354
355         return clk;
356 }
357
358 static void __init
359 of_at91_clk_periph_setup(struct device_node *np, struct at91_pmc *pmc, u8 type)
360 {
361         int num;
362         u32 id;
363         struct clk *clk;
364         const char *parent_name;
365         const char *name;
366         struct device_node *periphclknp;
367
368         parent_name = of_clk_get_parent_name(np, 0);
369         if (!parent_name)
370                 return;
371
372         num = of_get_child_count(np);
373         if (!num || num > PERIPHERAL_MAX)
374                 return;
375
376         for_each_child_of_node(np, periphclknp) {
377                 if (of_property_read_u32(periphclknp, "reg", &id))
378                         continue;
379
380                 if (id >= PERIPHERAL_MAX)
381                         continue;
382
383                 if (of_property_read_string(np, "clock-output-names", &name))
384                         name = periphclknp->name;
385
386                 if (type == PERIPHERAL_AT91RM9200) {
387                         clk = at91_clk_register_peripheral(pmc, name,
388                                                            parent_name, id);
389                 } else {
390                         struct clk_range range = CLK_RANGE(0, 0);
391
392                         of_at91_get_clk_range(periphclknp,
393                                               "atmel,clk-output-range",
394                                               &range);
395
396                         clk = at91_clk_register_sam9x5_peripheral(pmc, name,
397                                                                   parent_name,
398                                                                   id, &range);
399                 }
400
401                 if (IS_ERR(clk))
402                         continue;
403
404                 of_clk_add_provider(periphclknp, of_clk_src_simple_get, clk);
405         }
406 }
407
408 void __init of_at91rm9200_clk_periph_setup(struct device_node *np,
409                                            struct at91_pmc *pmc)
410 {
411         of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91RM9200);
412 }
413
414 void __init of_at91sam9x5_clk_periph_setup(struct device_node *np,
415                                            struct at91_pmc *pmc)
416 {
417         of_at91_clk_periph_setup(np, pmc, PERIPHERAL_AT91SAM9X5);
418 }