]> Git Repo - linux.git/blob - drivers/clk/zte/clk.c
Merge remote-tracking branches 'asoc/topic/max9878', 'asoc/topic/max98927', 'asoc...
[linux.git] / drivers / clk / zte / clk.c
1 /*
2  * Copyright 2014 Linaro Ltd.
3  * Copyright (C) 2014 ZTE Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  */
9
10 #include <linux/clk-provider.h>
11 #include <linux/err.h>
12 #include <linux/gcd.h>
13 #include <linux/io.h>
14 #include <linux/iopoll.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
17 #include <asm/div64.h>
18
19 #include "clk.h"
20
21 #define to_clk_zx_pll(_hw) container_of(_hw, struct clk_zx_pll, hw)
22 #define to_clk_zx_audio(_hw) container_of(_hw, struct clk_zx_audio, hw)
23
24 #define CFG0_CFG1_OFFSET 4
25 #define LOCK_FLAG 30
26 #define POWER_DOWN 31
27
28 static int rate_to_idx(struct clk_zx_pll *zx_pll, unsigned long rate)
29 {
30         const struct zx_pll_config *config = zx_pll->lookup_table;
31         int i;
32
33         for (i = 0; i < zx_pll->count; i++) {
34                 if (config[i].rate > rate)
35                         return i > 0 ? i - 1 : 0;
36
37                 if (config[i].rate == rate)
38                         return i;
39         }
40
41         return i - 1;
42 }
43
44 static int hw_to_idx(struct clk_zx_pll *zx_pll)
45 {
46         const struct zx_pll_config *config = zx_pll->lookup_table;
47         u32 hw_cfg0, hw_cfg1;
48         int i;
49
50         hw_cfg0 = readl_relaxed(zx_pll->reg_base);
51         hw_cfg1 = readl_relaxed(zx_pll->reg_base + CFG0_CFG1_OFFSET);
52
53         /* For matching the value in lookup table */
54         hw_cfg0 &= ~BIT(zx_pll->lock_bit);
55         hw_cfg0 |= BIT(zx_pll->pd_bit);
56
57         for (i = 0; i < zx_pll->count; i++) {
58                 if (hw_cfg0 == config[i].cfg0 && hw_cfg1 == config[i].cfg1)
59                         return i;
60         }
61
62         return -EINVAL;
63 }
64
65 static unsigned long zx_pll_recalc_rate(struct clk_hw *hw,
66                                         unsigned long parent_rate)
67 {
68         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
69         int idx;
70
71         idx = hw_to_idx(zx_pll);
72         if (unlikely(idx == -EINVAL))
73                 return 0;
74
75         return zx_pll->lookup_table[idx].rate;
76 }
77
78 static long zx_pll_round_rate(struct clk_hw *hw, unsigned long rate,
79                               unsigned long *prate)
80 {
81         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
82         int idx;
83
84         idx = rate_to_idx(zx_pll, rate);
85
86         return zx_pll->lookup_table[idx].rate;
87 }
88
89 static int zx_pll_set_rate(struct clk_hw *hw, unsigned long rate,
90                            unsigned long parent_rate)
91 {
92         /* Assume current cpu is not running on current PLL */
93         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
94         const struct zx_pll_config *config;
95         int idx;
96
97         idx = rate_to_idx(zx_pll, rate);
98         config = &zx_pll->lookup_table[idx];
99
100         writel_relaxed(config->cfg0, zx_pll->reg_base);
101         writel_relaxed(config->cfg1, zx_pll->reg_base + CFG0_CFG1_OFFSET);
102
103         return 0;
104 }
105
106 static int zx_pll_enable(struct clk_hw *hw)
107 {
108         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
109         u32 reg;
110
111         reg = readl_relaxed(zx_pll->reg_base);
112         writel_relaxed(reg & ~BIT(zx_pll->pd_bit), zx_pll->reg_base);
113
114         return readl_relaxed_poll_timeout(zx_pll->reg_base, reg,
115                                           reg & BIT(zx_pll->lock_bit), 0, 100);
116 }
117
118 static void zx_pll_disable(struct clk_hw *hw)
119 {
120         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
121         u32 reg;
122
123         reg = readl_relaxed(zx_pll->reg_base);
124         writel_relaxed(reg | BIT(zx_pll->pd_bit), zx_pll->reg_base);
125 }
126
127 static int zx_pll_is_enabled(struct clk_hw *hw)
128 {
129         struct clk_zx_pll *zx_pll = to_clk_zx_pll(hw);
130         u32 reg;
131
132         reg = readl_relaxed(zx_pll->reg_base);
133
134         return !(reg & BIT(zx_pll->pd_bit));
135 }
136
137 const struct clk_ops zx_pll_ops = {
138         .recalc_rate = zx_pll_recalc_rate,
139         .round_rate = zx_pll_round_rate,
140         .set_rate = zx_pll_set_rate,
141         .enable = zx_pll_enable,
142         .disable = zx_pll_disable,
143         .is_enabled = zx_pll_is_enabled,
144 };
145 EXPORT_SYMBOL(zx_pll_ops);
146
147 struct clk *clk_register_zx_pll(const char *name, const char *parent_name,
148                                 unsigned long flags, void __iomem *reg_base,
149                                 const struct zx_pll_config *lookup_table,
150                                 int count, spinlock_t *lock)
151 {
152         struct clk_zx_pll *zx_pll;
153         struct clk *clk;
154         struct clk_init_data init;
155
156         zx_pll = kzalloc(sizeof(*zx_pll), GFP_KERNEL);
157         if (!zx_pll)
158                 return ERR_PTR(-ENOMEM);
159
160         init.name = name;
161         init.ops = &zx_pll_ops;
162         init.flags = flags;
163         init.parent_names = parent_name ? &parent_name : NULL;
164         init.num_parents = parent_name ? 1 : 0;
165
166         zx_pll->reg_base = reg_base;
167         zx_pll->lookup_table = lookup_table;
168         zx_pll->count = count;
169         zx_pll->lock_bit = LOCK_FLAG;
170         zx_pll->pd_bit = POWER_DOWN;
171         zx_pll->lock = lock;
172         zx_pll->hw.init = &init;
173
174         clk = clk_register(NULL, &zx_pll->hw);
175         if (IS_ERR(clk))
176                 kfree(zx_pll);
177
178         return clk;
179 }
180
181 #define BPAR 1000000
182 static u32 calc_reg(u32 parent_rate, u32 rate)
183 {
184         u32 sel, integ, fra_div, tmp;
185         u64 tmp64 = (u64)parent_rate * BPAR;
186
187         do_div(tmp64, rate);
188         integ = (u32)tmp64 / BPAR;
189         integ = integ >> 1;
190
191         tmp = (u32)tmp64 % BPAR;
192         sel = tmp / BPAR;
193
194         tmp = tmp % BPAR;
195         fra_div = tmp * 0xff / BPAR;
196         tmp = (sel << 24) | (integ << 16) | (0xff << 8) | fra_div;
197
198         /* Set I2S integer divider as 1. This bit is reserved for SPDIF
199          * and do no harm.
200          */
201         tmp |= BIT(28);
202         return tmp;
203 }
204
205 static u32 calc_rate(u32 reg, u32 parent_rate)
206 {
207         u32 sel, integ, fra_div, tmp;
208         u64 tmp64 = (u64)parent_rate * BPAR;
209
210         tmp = reg;
211         sel = (tmp >> 24) & BIT(0);
212         integ = (tmp >> 16) & 0xff;
213         fra_div = tmp & 0xff;
214
215         tmp = fra_div * BPAR;
216         tmp = tmp / 0xff;
217         tmp += sel * BPAR;
218         tmp += 2 * integ * BPAR;
219         do_div(tmp64, tmp);
220
221         return (u32)tmp64;
222 }
223
224 static unsigned long zx_audio_recalc_rate(struct clk_hw *hw,
225                                           unsigned long parent_rate)
226 {
227         struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
228         u32 reg;
229
230         reg = readl_relaxed(zx_audio->reg_base);
231         return calc_rate(reg, parent_rate);
232 }
233
234 static long zx_audio_round_rate(struct clk_hw *hw, unsigned long rate,
235                                 unsigned long *prate)
236 {
237         u32 reg;
238
239         if (rate * 2 > *prate)
240                 return -EINVAL;
241
242         reg = calc_reg(*prate, rate);
243         return calc_rate(reg, *prate);
244 }
245
246 static int zx_audio_set_rate(struct clk_hw *hw, unsigned long rate,
247                              unsigned long parent_rate)
248 {
249         struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
250         u32 reg;
251
252         reg = calc_reg(parent_rate, rate);
253         writel_relaxed(reg, zx_audio->reg_base);
254
255         return 0;
256 }
257
258 #define ZX_AUDIO_EN BIT(25)
259 static int zx_audio_enable(struct clk_hw *hw)
260 {
261         struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
262         u32 reg;
263
264         reg = readl_relaxed(zx_audio->reg_base);
265         writel_relaxed(reg & ~ZX_AUDIO_EN, zx_audio->reg_base);
266         return 0;
267 }
268
269 static void zx_audio_disable(struct clk_hw *hw)
270 {
271         struct clk_zx_audio *zx_audio = to_clk_zx_audio(hw);
272         u32 reg;
273
274         reg = readl_relaxed(zx_audio->reg_base);
275         writel_relaxed(reg | ZX_AUDIO_EN, zx_audio->reg_base);
276 }
277
278 static const struct clk_ops zx_audio_ops = {
279         .recalc_rate = zx_audio_recalc_rate,
280         .round_rate = zx_audio_round_rate,
281         .set_rate = zx_audio_set_rate,
282         .enable = zx_audio_enable,
283         .disable = zx_audio_disable,
284 };
285
286 struct clk *clk_register_zx_audio(const char *name,
287                                   const char * const parent_name,
288                                   unsigned long flags,
289                                   void __iomem *reg_base)
290 {
291         struct clk_zx_audio *zx_audio;
292         struct clk *clk;
293         struct clk_init_data init;
294
295         zx_audio = kzalloc(sizeof(*zx_audio), GFP_KERNEL);
296         if (!zx_audio)
297                 return ERR_PTR(-ENOMEM);
298
299         init.name = name;
300         init.ops = &zx_audio_ops;
301         init.flags = flags;
302         init.parent_names = parent_name ? &parent_name : NULL;
303         init.num_parents = parent_name ? 1 : 0;
304
305         zx_audio->reg_base = reg_base;
306         zx_audio->hw.init = &init;
307
308         clk = clk_register(NULL, &zx_audio->hw);
309         if (IS_ERR(clk))
310                 kfree(zx_audio);
311
312         return clk;
313 }
314
315 #define CLK_AUDIO_DIV_FRAC      BIT(0)
316 #define CLK_AUDIO_DIV_INT       BIT(1)
317 #define CLK_AUDIO_DIV_UNCOMMON  BIT(1)
318
319 #define CLK_AUDIO_DIV_FRAC_NSHIFT       16
320 #define CLK_AUDIO_DIV_INT_FRAC_RE       BIT(16)
321 #define CLK_AUDIO_DIV_INT_FRAC_MAX      (0xffff)
322 #define CLK_AUDIO_DIV_INT_FRAC_MIN      (0x2)
323 #define CLK_AUDIO_DIV_INT_INT_SHIFT     24
324 #define CLK_AUDIO_DIV_INT_INT_WIDTH     4
325
326 struct zx_clk_audio_div_table {
327         unsigned long rate;
328         unsigned int int_reg;
329         unsigned int frac_reg;
330 };
331
332 #define to_clk_zx_audio_div(_hw) container_of(_hw, struct clk_zx_audio_divider, hw)
333
334 static unsigned long audio_calc_rate(struct clk_zx_audio_divider *audio_div,
335                                      u32 reg_frac, u32 reg_int,
336                                      unsigned long parent_rate)
337 {
338         unsigned long rate, m, n;
339
340         m = reg_frac & 0xffff;
341         n = (reg_frac >> 16) & 0xffff;
342
343         m = (reg_int & 0xffff) * n + m;
344         rate = (parent_rate * n) / m;
345
346         return rate;
347 }
348
349 static void audio_calc_reg(struct clk_zx_audio_divider *audio_div,
350                            struct zx_clk_audio_div_table *div_table,
351                            unsigned long rate, unsigned long parent_rate)
352 {
353         unsigned int reg_int, reg_frac;
354         unsigned long m, n, div;
355
356         reg_int = parent_rate / rate;
357
358         if (reg_int > CLK_AUDIO_DIV_INT_FRAC_MAX)
359                 reg_int = CLK_AUDIO_DIV_INT_FRAC_MAX;
360         else if (reg_int < CLK_AUDIO_DIV_INT_FRAC_MIN)
361                 reg_int = 0;
362         m = parent_rate - rate * reg_int;
363         n = rate;
364
365         div = gcd(m, n);
366         m = m / div;
367         n = n / div;
368
369         if ((m >> 16) || (n >> 16)) {
370                 if (m > n) {
371                         n = n * 0xffff / m;
372                         m = 0xffff;
373                 } else {
374                         m = m * 0xffff / n;
375                         n = 0xffff;
376                 }
377         }
378         reg_frac = m | (n << 16);
379
380         div_table->rate = parent_rate * n / (reg_int * n + m);
381         div_table->int_reg = reg_int;
382         div_table->frac_reg = reg_frac;
383 }
384
385 static unsigned long zx_audio_div_recalc_rate(struct clk_hw *hw,
386                                           unsigned long parent_rate)
387 {
388         struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
389         u32 reg_frac, reg_int;
390
391         reg_frac = readl_relaxed(zx_audio_div->reg_base);
392         reg_int = readl_relaxed(zx_audio_div->reg_base + 0x4);
393
394         return audio_calc_rate(zx_audio_div, reg_frac, reg_int, parent_rate);
395 }
396
397 static long zx_audio_div_round_rate(struct clk_hw *hw, unsigned long rate,
398                                 unsigned long *prate)
399 {
400         struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
401         struct zx_clk_audio_div_table divt;
402
403         audio_calc_reg(zx_audio_div, &divt, rate, *prate);
404
405         return audio_calc_rate(zx_audio_div, divt.frac_reg, divt.int_reg, *prate);
406 }
407
408 static int zx_audio_div_set_rate(struct clk_hw *hw, unsigned long rate,
409                                     unsigned long parent_rate)
410 {
411         struct clk_zx_audio_divider *zx_audio_div = to_clk_zx_audio_div(hw);
412         struct zx_clk_audio_div_table divt;
413         unsigned int val;
414
415         audio_calc_reg(zx_audio_div, &divt, rate, parent_rate);
416         if (divt.rate != rate)
417                 pr_debug("the real rate is:%ld", divt.rate);
418
419         writel_relaxed(divt.frac_reg, zx_audio_div->reg_base);
420
421         val = readl_relaxed(zx_audio_div->reg_base + 0x4);
422         val &= ~0xffff;
423         val |= divt.int_reg | CLK_AUDIO_DIV_INT_FRAC_RE;
424         writel_relaxed(val, zx_audio_div->reg_base + 0x4);
425
426         mdelay(1);
427
428         val = readl_relaxed(zx_audio_div->reg_base + 0x4);
429         val &= ~CLK_AUDIO_DIV_INT_FRAC_RE;
430         writel_relaxed(val, zx_audio_div->reg_base + 0x4);
431
432         return 0;
433 }
434
435 const struct clk_ops zx_audio_div_ops = {
436         .recalc_rate = zx_audio_div_recalc_rate,
437         .round_rate = zx_audio_div_round_rate,
438         .set_rate = zx_audio_div_set_rate,
439 };
This page took 0.058747 seconds and 4 git commands to generate.