diff options
Diffstat (limited to 'drivers/clk/rockchip')
-rw-r--r-- | drivers/clk/rockchip/Makefile | 6 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-pll.c | 431 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3188.c | 672 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk-rk3288.c | 717 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.c | 244 | ||||
-rw-r--r-- | drivers/clk/rockchip/clk.h | 347 | ||||
-rw-r--r-- | drivers/clk/rockchip/softrst.c | 118 |
7 files changed, 2535 insertions, 0 deletions
diff --git a/drivers/clk/rockchip/Makefile b/drivers/clk/rockchip/Makefile index 8d3aefad2e73..ee6b077381e1 100644 --- a/drivers/clk/rockchip/Makefile +++ b/drivers/clk/rockchip/Makefile | |||
@@ -3,3 +3,9 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y += clk-rockchip.o | 5 | obj-y += clk-rockchip.o |
6 | obj-y += clk.o | ||
7 | obj-y += clk-pll.o | ||
8 | obj-$(CONFIG_RESET_CONTROLLER) += softrst.o | ||
9 | |||
10 | obj-y += clk-rk3188.o | ||
11 | obj-y += clk-rk3288.o | ||
diff --git a/drivers/clk/rockchip/clk-pll.c b/drivers/clk/rockchip/clk-pll.c new file mode 100644 index 000000000000..f2a1c7abf4d9 --- /dev/null +++ b/drivers/clk/rockchip/clk-pll.c | |||
@@ -0,0 +1,431 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <asm/div64.h> | ||
17 | #include <linux/slab.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/clk.h> | ||
21 | #include <linux/clk-provider.h> | ||
22 | #include <linux/regmap.h> | ||
23 | #include "clk.h" | ||
24 | |||
25 | #define PLL_MODE_MASK 0x3 | ||
26 | #define PLL_MODE_SLOW 0x0 | ||
27 | #define PLL_MODE_NORM 0x1 | ||
28 | #define PLL_MODE_DEEP 0x2 | ||
29 | |||
30 | struct rockchip_clk_pll { | ||
31 | struct clk_hw hw; | ||
32 | |||
33 | struct clk_mux pll_mux; | ||
34 | const struct clk_ops *pll_mux_ops; | ||
35 | |||
36 | struct notifier_block clk_nb; | ||
37 | bool rate_change_remuxed; | ||
38 | |||
39 | void __iomem *reg_base; | ||
40 | int lock_offset; | ||
41 | unsigned int lock_shift; | ||
42 | enum rockchip_pll_type type; | ||
43 | const struct rockchip_pll_rate_table *rate_table; | ||
44 | unsigned int rate_count; | ||
45 | spinlock_t *lock; | ||
46 | }; | ||
47 | |||
48 | #define to_rockchip_clk_pll(_hw) container_of(_hw, struct rockchip_clk_pll, hw) | ||
49 | #define to_rockchip_clk_pll_nb(nb) \ | ||
50 | container_of(nb, struct rockchip_clk_pll, clk_nb) | ||
51 | |||
52 | static const struct rockchip_pll_rate_table *rockchip_get_pll_settings( | ||
53 | struct rockchip_clk_pll *pll, unsigned long rate) | ||
54 | { | ||
55 | const struct rockchip_pll_rate_table *rate_table = pll->rate_table; | ||
56 | int i; | ||
57 | |||
58 | for (i = 0; i < pll->rate_count; i++) { | ||
59 | if (rate == rate_table[i].rate) | ||
60 | return &rate_table[i]; | ||
61 | } | ||
62 | |||
63 | return NULL; | ||
64 | } | ||
65 | |||
66 | static long rockchip_pll_round_rate(struct clk_hw *hw, | ||
67 | unsigned long drate, unsigned long *prate) | ||
68 | { | ||
69 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
70 | const struct rockchip_pll_rate_table *rate_table = pll->rate_table; | ||
71 | int i; | ||
72 | |||
73 | /* Assumming rate_table is in descending order */ | ||
74 | for (i = 0; i < pll->rate_count; i++) { | ||
75 | if (drate >= rate_table[i].rate) | ||
76 | return rate_table[i].rate; | ||
77 | } | ||
78 | |||
79 | /* return minimum supported value */ | ||
80 | return rate_table[i - 1].rate; | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Wait for the pll to reach the locked state. | ||
85 | * The calling set_rate function is responsible for making sure the | ||
86 | * grf regmap is available. | ||
87 | */ | ||
88 | static int rockchip_pll_wait_lock(struct rockchip_clk_pll *pll) | ||
89 | { | ||
90 | struct regmap *grf = rockchip_clk_get_grf(); | ||
91 | unsigned int val; | ||
92 | int delay = 24000000, ret; | ||
93 | |||
94 | while (delay > 0) { | ||
95 | ret = regmap_read(grf, pll->lock_offset, &val); | ||
96 | if (ret) { | ||
97 | pr_err("%s: failed to read pll lock status: %d\n", | ||
98 | __func__, ret); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | if (val & BIT(pll->lock_shift)) | ||
103 | return 0; | ||
104 | delay--; | ||
105 | } | ||
106 | |||
107 | pr_err("%s: timeout waiting for pll to lock\n", __func__); | ||
108 | return -ETIMEDOUT; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * Set pll mux when changing the pll rate. | ||
113 | * This makes sure to move the pll mux away from the actual pll before | ||
114 | * changing its rate and back to the original parent after the change. | ||
115 | */ | ||
116 | static int rockchip_pll_notifier_cb(struct notifier_block *nb, | ||
117 | unsigned long event, void *data) | ||
118 | { | ||
119 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll_nb(nb); | ||
120 | struct clk_mux *pll_mux = &pll->pll_mux; | ||
121 | const struct clk_ops *pll_mux_ops = pll->pll_mux_ops; | ||
122 | int cur_parent; | ||
123 | |||
124 | switch (event) { | ||
125 | case PRE_RATE_CHANGE: | ||
126 | cur_parent = pll_mux_ops->get_parent(&pll_mux->hw); | ||
127 | if (cur_parent == PLL_MODE_NORM) { | ||
128 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_SLOW); | ||
129 | pll->rate_change_remuxed = 1; | ||
130 | } | ||
131 | break; | ||
132 | case POST_RATE_CHANGE: | ||
133 | if (pll->rate_change_remuxed) { | ||
134 | pll_mux_ops->set_parent(&pll_mux->hw, PLL_MODE_NORM); | ||
135 | pll->rate_change_remuxed = 0; | ||
136 | } | ||
137 | break; | ||
138 | } | ||
139 | |||
140 | return NOTIFY_OK; | ||
141 | } | ||
142 | |||
143 | /** | ||
144 | * PLL used in RK3066, RK3188 and RK3288 | ||
145 | */ | ||
146 | |||
147 | #define RK3066_PLL_RESET_DELAY(nr) ((nr * 500) / 24 + 1) | ||
148 | |||
149 | #define RK3066_PLLCON(i) (i * 0x4) | ||
150 | #define RK3066_PLLCON0_OD_MASK 0xf | ||
151 | #define RK3066_PLLCON0_OD_SHIFT 0 | ||
152 | #define RK3066_PLLCON0_NR_MASK 0x3f | ||
153 | #define RK3066_PLLCON0_NR_SHIFT 8 | ||
154 | #define RK3066_PLLCON1_NF_MASK 0x1fff | ||
155 | #define RK3066_PLLCON1_NF_SHIFT 0 | ||
156 | #define RK3066_PLLCON2_BWADJ_MASK 0xfff | ||
157 | #define RK3066_PLLCON2_BWADJ_SHIFT 0 | ||
158 | #define RK3066_PLLCON3_RESET (1 << 5) | ||
159 | #define RK3066_PLLCON3_PWRDOWN (1 << 1) | ||
160 | #define RK3066_PLLCON3_BYPASS (1 << 0) | ||
161 | |||
162 | static unsigned long rockchip_rk3066_pll_recalc_rate(struct clk_hw *hw, | ||
163 | unsigned long prate) | ||
164 | { | ||
165 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
166 | u64 nf, nr, no, rate64 = prate; | ||
167 | u32 pllcon; | ||
168 | |||
169 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(3)); | ||
170 | if (pllcon & RK3066_PLLCON3_BYPASS) { | ||
171 | pr_debug("%s: pll %s is bypassed\n", __func__, | ||
172 | __clk_get_name(hw->clk)); | ||
173 | return prate; | ||
174 | } | ||
175 | |||
176 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(1)); | ||
177 | nf = (pllcon >> RK3066_PLLCON1_NF_SHIFT) & RK3066_PLLCON1_NF_MASK; | ||
178 | |||
179 | pllcon = readl_relaxed(pll->reg_base + RK3066_PLLCON(0)); | ||
180 | nr = (pllcon >> RK3066_PLLCON0_NR_SHIFT) & RK3066_PLLCON0_NR_MASK; | ||
181 | no = (pllcon >> RK3066_PLLCON0_OD_SHIFT) & RK3066_PLLCON0_OD_MASK; | ||
182 | |||
183 | rate64 *= (nf + 1); | ||
184 | do_div(rate64, nr + 1); | ||
185 | do_div(rate64, no + 1); | ||
186 | |||
187 | return (unsigned long)rate64; | ||
188 | } | ||
189 | |||
190 | static int rockchip_rk3066_pll_set_rate(struct clk_hw *hw, unsigned long drate, | ||
191 | unsigned long prate) | ||
192 | { | ||
193 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
194 | const struct rockchip_pll_rate_table *rate; | ||
195 | unsigned long old_rate = rockchip_rk3066_pll_recalc_rate(hw, prate); | ||
196 | struct regmap *grf = rockchip_clk_get_grf(); | ||
197 | int ret; | ||
198 | |||
199 | if (IS_ERR(grf)) { | ||
200 | pr_debug("%s: grf regmap not available, aborting rate change\n", | ||
201 | __func__); | ||
202 | return PTR_ERR(grf); | ||
203 | } | ||
204 | |||
205 | pr_debug("%s: changing %s from %lu to %lu with a parent rate of %lu\n", | ||
206 | __func__, __clk_get_name(hw->clk), old_rate, drate, prate); | ||
207 | |||
208 | /* Get required rate settings from table */ | ||
209 | rate = rockchip_get_pll_settings(pll, drate); | ||
210 | if (!rate) { | ||
211 | pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__, | ||
212 | drate, __clk_get_name(hw->clk)); | ||
213 | return -EINVAL; | ||
214 | } | ||
215 | |||
216 | pr_debug("%s: rate settings for %lu (nr, no, nf): (%d, %d, %d)\n", | ||
217 | __func__, rate->rate, rate->nr, rate->no, rate->nf); | ||
218 | |||
219 | /* enter reset mode */ | ||
220 | writel(HIWORD_UPDATE(RK3066_PLLCON3_RESET, RK3066_PLLCON3_RESET, 0), | ||
221 | pll->reg_base + RK3066_PLLCON(3)); | ||
222 | |||
223 | /* update pll values */ | ||
224 | writel(HIWORD_UPDATE(rate->nr - 1, RK3066_PLLCON0_NR_MASK, | ||
225 | RK3066_PLLCON0_NR_SHIFT) | | ||
226 | HIWORD_UPDATE(rate->no - 1, RK3066_PLLCON0_OD_MASK, | ||
227 | RK3066_PLLCON0_OD_SHIFT), | ||
228 | pll->reg_base + RK3066_PLLCON(0)); | ||
229 | |||
230 | writel_relaxed(HIWORD_UPDATE(rate->nf - 1, RK3066_PLLCON1_NF_MASK, | ||
231 | RK3066_PLLCON1_NF_SHIFT), | ||
232 | pll->reg_base + RK3066_PLLCON(1)); | ||
233 | writel_relaxed(HIWORD_UPDATE(rate->bwadj, RK3066_PLLCON2_BWADJ_MASK, | ||
234 | RK3066_PLLCON2_BWADJ_SHIFT), | ||
235 | pll->reg_base + RK3066_PLLCON(2)); | ||
236 | |||
237 | /* leave reset and wait the reset_delay */ | ||
238 | writel(HIWORD_UPDATE(0, RK3066_PLLCON3_RESET, 0), | ||
239 | pll->reg_base + RK3066_PLLCON(3)); | ||
240 | udelay(RK3066_PLL_RESET_DELAY(rate->nr)); | ||
241 | |||
242 | /* wait for the pll to lock */ | ||
243 | ret = rockchip_pll_wait_lock(pll); | ||
244 | if (ret) { | ||
245 | pr_warn("%s: pll did not lock, trying to restore old rate %lu\n", | ||
246 | __func__, old_rate); | ||
247 | rockchip_rk3066_pll_set_rate(hw, old_rate, prate); | ||
248 | } | ||
249 | |||
250 | return ret; | ||
251 | } | ||
252 | |||
253 | static int rockchip_rk3066_pll_enable(struct clk_hw *hw) | ||
254 | { | ||
255 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
256 | |||
257 | writel(HIWORD_UPDATE(0, RK3066_PLLCON3_PWRDOWN, 0), | ||
258 | pll->reg_base + RK3066_PLLCON(3)); | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static void rockchip_rk3066_pll_disable(struct clk_hw *hw) | ||
264 | { | ||
265 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
266 | |||
267 | writel(HIWORD_UPDATE(RK3066_PLLCON3_PWRDOWN, | ||
268 | RK3066_PLLCON3_PWRDOWN, 0), | ||
269 | pll->reg_base + RK3066_PLLCON(3)); | ||
270 | } | ||
271 | |||
272 | static int rockchip_rk3066_pll_is_enabled(struct clk_hw *hw) | ||
273 | { | ||
274 | struct rockchip_clk_pll *pll = to_rockchip_clk_pll(hw); | ||
275 | u32 pllcon = readl(pll->reg_base + RK3066_PLLCON(3)); | ||
276 | |||
277 | return !(pllcon & RK3066_PLLCON3_PWRDOWN); | ||
278 | } | ||
279 | |||
280 | static const struct clk_ops rockchip_rk3066_pll_clk_norate_ops = { | ||
281 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, | ||
282 | .enable = rockchip_rk3066_pll_enable, | ||
283 | .disable = rockchip_rk3066_pll_disable, | ||
284 | .is_enabled = rockchip_rk3066_pll_is_enabled, | ||
285 | }; | ||
286 | |||
287 | static const struct clk_ops rockchip_rk3066_pll_clk_ops = { | ||
288 | .recalc_rate = rockchip_rk3066_pll_recalc_rate, | ||
289 | .round_rate = rockchip_pll_round_rate, | ||
290 | .set_rate = rockchip_rk3066_pll_set_rate, | ||
291 | .enable = rockchip_rk3066_pll_enable, | ||
292 | .disable = rockchip_rk3066_pll_disable, | ||
293 | .is_enabled = rockchip_rk3066_pll_is_enabled, | ||
294 | }; | ||
295 | |||
296 | /* | ||
297 | * Common registering of pll clocks | ||
298 | */ | ||
299 | |||
300 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | ||
301 | const char *name, const char **parent_names, u8 num_parents, | ||
302 | void __iomem *base, int con_offset, int grf_lock_offset, | ||
303 | int lock_shift, int mode_offset, int mode_shift, | ||
304 | struct rockchip_pll_rate_table *rate_table, | ||
305 | spinlock_t *lock) | ||
306 | { | ||
307 | const char *pll_parents[3]; | ||
308 | struct clk_init_data init; | ||
309 | struct rockchip_clk_pll *pll; | ||
310 | struct clk_mux *pll_mux; | ||
311 | struct clk *pll_clk, *mux_clk; | ||
312 | char pll_name[20]; | ||
313 | int ret; | ||
314 | |||
315 | if (num_parents != 2) { | ||
316 | pr_err("%s: needs two parent clocks\n", __func__); | ||
317 | return ERR_PTR(-EINVAL); | ||
318 | } | ||
319 | |||
320 | /* name the actual pll */ | ||
321 | snprintf(pll_name, sizeof(pll_name), "pll_%s", name); | ||
322 | |||
323 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | ||
324 | if (!pll) | ||
325 | return ERR_PTR(-ENOMEM); | ||
326 | |||
327 | init.name = pll_name; | ||
328 | |||
329 | /* keep all plls untouched for now */ | ||
330 | init.flags = CLK_IGNORE_UNUSED; | ||
331 | |||
332 | init.parent_names = &parent_names[0]; | ||
333 | init.num_parents = 1; | ||
334 | |||
335 | if (rate_table) { | ||
336 | int len; | ||
337 | |||
338 | /* find count of rates in rate_table */ | ||
339 | for (len = 0; rate_table[len].rate != 0; ) | ||
340 | len++; | ||
341 | |||
342 | pll->rate_count = len; | ||
343 | pll->rate_table = kmemdup(rate_table, | ||
344 | pll->rate_count * | ||
345 | sizeof(struct rockchip_pll_rate_table), | ||
346 | GFP_KERNEL); | ||
347 | WARN(!pll->rate_table, | ||
348 | "%s: could not allocate rate table for %s\n", | ||
349 | __func__, name); | ||
350 | } | ||
351 | |||
352 | switch (pll_type) { | ||
353 | case pll_rk3066: | ||
354 | if (!pll->rate_table) | ||
355 | init.ops = &rockchip_rk3066_pll_clk_norate_ops; | ||
356 | else | ||
357 | init.ops = &rockchip_rk3066_pll_clk_ops; | ||
358 | break; | ||
359 | default: | ||
360 | pr_warn("%s: Unknown pll type for pll clk %s\n", | ||
361 | __func__, name); | ||
362 | } | ||
363 | |||
364 | pll->hw.init = &init; | ||
365 | pll->type = pll_type; | ||
366 | pll->reg_base = base + con_offset; | ||
367 | pll->lock_offset = grf_lock_offset; | ||
368 | pll->lock_shift = lock_shift; | ||
369 | pll->lock = lock; | ||
370 | pll->clk_nb.notifier_call = rockchip_pll_notifier_cb; | ||
371 | |||
372 | pll_clk = clk_register(NULL, &pll->hw); | ||
373 | if (IS_ERR(pll_clk)) { | ||
374 | pr_err("%s: failed to register pll clock %s : %ld\n", | ||
375 | __func__, name, PTR_ERR(pll_clk)); | ||
376 | mux_clk = pll_clk; | ||
377 | goto err_pll; | ||
378 | } | ||
379 | |||
380 | ret = clk_notifier_register(pll_clk, &pll->clk_nb); | ||
381 | if (ret) { | ||
382 | pr_err("%s: failed to register clock notifier for %s : %d\n", | ||
383 | __func__, name, ret); | ||
384 | mux_clk = ERR_PTR(ret); | ||
385 | goto err_pll_notifier; | ||
386 | } | ||
387 | |||
388 | /* create the mux on top of the real pll */ | ||
389 | pll->pll_mux_ops = &clk_mux_ops; | ||
390 | pll_mux = &pll->pll_mux; | ||
391 | |||
392 | /* the actual muxing is xin24m, pll-output, xin32k */ | ||
393 | pll_parents[0] = parent_names[0]; | ||
394 | pll_parents[1] = pll_name; | ||
395 | pll_parents[2] = parent_names[1]; | ||
396 | |||
397 | init.name = name; | ||
398 | init.flags = CLK_SET_RATE_PARENT; | ||
399 | init.ops = pll->pll_mux_ops; | ||
400 | init.parent_names = pll_parents; | ||
401 | init.num_parents = ARRAY_SIZE(pll_parents); | ||
402 | |||
403 | pll_mux->reg = base + mode_offset; | ||
404 | pll_mux->shift = mode_shift; | ||
405 | pll_mux->mask = PLL_MODE_MASK; | ||
406 | pll_mux->flags = 0; | ||
407 | pll_mux->lock = lock; | ||
408 | pll_mux->hw.init = &init; | ||
409 | |||
410 | if (pll_type == pll_rk3066) | ||
411 | pll_mux->flags |= CLK_MUX_HIWORD_MASK; | ||
412 | |||
413 | mux_clk = clk_register(NULL, &pll_mux->hw); | ||
414 | if (IS_ERR(mux_clk)) | ||
415 | goto err_mux; | ||
416 | |||
417 | return mux_clk; | ||
418 | |||
419 | err_mux: | ||
420 | ret = clk_notifier_unregister(pll_clk, &pll->clk_nb); | ||
421 | if (ret) { | ||
422 | pr_err("%s: could not unregister clock notifier in error path : %d\n", | ||
423 | __func__, ret); | ||
424 | return mux_clk; | ||
425 | } | ||
426 | err_pll_notifier: | ||
427 | clk_unregister(pll_clk); | ||
428 | err_pll: | ||
429 | kfree(pll); | ||
430 | return mux_clk; | ||
431 | } | ||
diff --git a/drivers/clk/rockchip/clk-rk3188.c b/drivers/clk/rockchip/clk-rk3188.c new file mode 100644 index 000000000000..a83a6d8d0fb6 --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3188.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <dt-bindings/clock/rk3188-cru-common.h> | ||
20 | #include "clk.h" | ||
21 | |||
22 | #define RK3188_GRF_SOC_STATUS 0xac | ||
23 | |||
24 | enum rk3188_plls { | ||
25 | apll, cpll, dpll, gpll, | ||
26 | }; | ||
27 | |||
28 | struct rockchip_pll_rate_table rk3188_pll_rates[] = { | ||
29 | RK3066_PLL_RATE(2208000000, 1, 92, 1), | ||
30 | RK3066_PLL_RATE(2184000000, 1, 91, 1), | ||
31 | RK3066_PLL_RATE(2160000000, 1, 90, 1), | ||
32 | RK3066_PLL_RATE(2136000000, 1, 89, 1), | ||
33 | RK3066_PLL_RATE(2112000000, 1, 88, 1), | ||
34 | RK3066_PLL_RATE(2088000000, 1, 87, 1), | ||
35 | RK3066_PLL_RATE(2064000000, 1, 86, 1), | ||
36 | RK3066_PLL_RATE(2040000000, 1, 85, 1), | ||
37 | RK3066_PLL_RATE(2016000000, 1, 84, 1), | ||
38 | RK3066_PLL_RATE(1992000000, 1, 83, 1), | ||
39 | RK3066_PLL_RATE(1968000000, 1, 82, 1), | ||
40 | RK3066_PLL_RATE(1944000000, 1, 81, 1), | ||
41 | RK3066_PLL_RATE(1920000000, 1, 80, 1), | ||
42 | RK3066_PLL_RATE(1896000000, 1, 79, 1), | ||
43 | RK3066_PLL_RATE(1872000000, 1, 78, 1), | ||
44 | RK3066_PLL_RATE(1848000000, 1, 77, 1), | ||
45 | RK3066_PLL_RATE(1824000000, 1, 76, 1), | ||
46 | RK3066_PLL_RATE(1800000000, 1, 75, 1), | ||
47 | RK3066_PLL_RATE(1776000000, 1, 74, 1), | ||
48 | RK3066_PLL_RATE(1752000000, 1, 73, 1), | ||
49 | RK3066_PLL_RATE(1728000000, 1, 72, 1), | ||
50 | RK3066_PLL_RATE(1704000000, 1, 71, 1), | ||
51 | RK3066_PLL_RATE(1680000000, 1, 70, 1), | ||
52 | RK3066_PLL_RATE(1656000000, 1, 69, 1), | ||
53 | RK3066_PLL_RATE(1632000000, 1, 68, 1), | ||
54 | RK3066_PLL_RATE(1608000000, 1, 67, 1), | ||
55 | RK3066_PLL_RATE(1560000000, 1, 65, 1), | ||
56 | RK3066_PLL_RATE(1512000000, 1, 63, 1), | ||
57 | RK3066_PLL_RATE(1488000000, 1, 62, 1), | ||
58 | RK3066_PLL_RATE(1464000000, 1, 61, 1), | ||
59 | RK3066_PLL_RATE(1440000000, 1, 60, 1), | ||
60 | RK3066_PLL_RATE(1416000000, 1, 59, 1), | ||
61 | RK3066_PLL_RATE(1392000000, 1, 58, 1), | ||
62 | RK3066_PLL_RATE(1368000000, 1, 57, 1), | ||
63 | RK3066_PLL_RATE(1344000000, 1, 56, 1), | ||
64 | RK3066_PLL_RATE(1320000000, 1, 55, 1), | ||
65 | RK3066_PLL_RATE(1296000000, 1, 54, 1), | ||
66 | RK3066_PLL_RATE(1272000000, 1, 53, 1), | ||
67 | RK3066_PLL_RATE(1248000000, 1, 52, 1), | ||
68 | RK3066_PLL_RATE(1224000000, 1, 51, 1), | ||
69 | RK3066_PLL_RATE(1200000000, 1, 50, 1), | ||
70 | RK3066_PLL_RATE(1188000000, 2, 99, 1), | ||
71 | RK3066_PLL_RATE(1176000000, 1, 49, 1), | ||
72 | RK3066_PLL_RATE(1128000000, 1, 47, 1), | ||
73 | RK3066_PLL_RATE(1104000000, 1, 46, 1), | ||
74 | RK3066_PLL_RATE(1008000000, 1, 84, 2), | ||
75 | RK3066_PLL_RATE( 912000000, 1, 76, 2), | ||
76 | RK3066_PLL_RATE( 891000000, 8, 594, 2), | ||
77 | RK3066_PLL_RATE( 888000000, 1, 74, 2), | ||
78 | RK3066_PLL_RATE( 816000000, 1, 68, 2), | ||
79 | RK3066_PLL_RATE( 798000000, 2, 133, 2), | ||
80 | RK3066_PLL_RATE( 792000000, 1, 66, 2), | ||
81 | RK3066_PLL_RATE( 768000000, 1, 64, 2), | ||
82 | RK3066_PLL_RATE( 742500000, 8, 495, 2), | ||
83 | RK3066_PLL_RATE( 696000000, 1, 58, 2), | ||
84 | RK3066_PLL_RATE( 600000000, 1, 50, 2), | ||
85 | RK3066_PLL_RATE( 594000000, 2, 198, 4), | ||
86 | RK3066_PLL_RATE( 552000000, 1, 46, 2), | ||
87 | RK3066_PLL_RATE( 504000000, 1, 84, 4), | ||
88 | RK3066_PLL_RATE( 456000000, 1, 76, 4), | ||
89 | RK3066_PLL_RATE( 408000000, 1, 68, 4), | ||
90 | RK3066_PLL_RATE( 384000000, 2, 128, 4), | ||
91 | RK3066_PLL_RATE( 360000000, 1, 60, 4), | ||
92 | RK3066_PLL_RATE( 312000000, 1, 52, 4), | ||
93 | RK3066_PLL_RATE( 300000000, 1, 50, 4), | ||
94 | RK3066_PLL_RATE( 297000000, 2, 198, 8), | ||
95 | RK3066_PLL_RATE( 252000000, 1, 84, 8), | ||
96 | RK3066_PLL_RATE( 216000000, 1, 72, 8), | ||
97 | RK3066_PLL_RATE( 148500000, 2, 99, 8), | ||
98 | RK3066_PLL_RATE( 126000000, 1, 84, 16), | ||
99 | RK3066_PLL_RATE( 48000000, 1, 64, 32), | ||
100 | { /* sentinel */ }, | ||
101 | }; | ||
102 | |||
103 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; | ||
104 | PNAME(mux_armclk_p) = { "apll", "gpll_armclk" }; | ||
105 | PNAME(mux_ddrphy_p) = { "dpll", "gpll_ddr" }; | ||
106 | PNAME(mux_pll_src_gpll_cpll_p) = { "gpll", "cpll" }; | ||
107 | PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; | ||
108 | PNAME(mux_aclk_cpu_p) = { "apll", "gpll" }; | ||
109 | PNAME(mux_sclk_cif0_p) = { "cif0_pre", "xin24m" }; | ||
110 | PNAME(mux_sclk_i2s0_p) = { "i2s0_pre", "i2s0_frac", "xin12m" }; | ||
111 | PNAME(mux_sclk_spdif_p) = { "spdif_src", "spdif_frac", "xin12m" }; | ||
112 | PNAME(mux_sclk_uart0_p) = { "uart0_pre", "uart0_frac", "xin24m" }; | ||
113 | PNAME(mux_sclk_uart1_p) = { "uart1_pre", "uart1_frac", "xin24m" }; | ||
114 | PNAME(mux_sclk_uart2_p) = { "uart2_pre", "uart2_frac", "xin24m" }; | ||
115 | PNAME(mux_sclk_uart3_p) = { "uart3_pre", "uart3_frac", "xin24m" }; | ||
116 | PNAME(mux_sclk_hsadc_p) = { "hsadc_src", "hsadc_frac", "ext_hsadc" }; | ||
117 | PNAME(mux_mac_p) = { "gpll", "dpll" }; | ||
118 | PNAME(mux_sclk_macref_p) = { "mac_src", "ext_rmii" }; | ||
119 | |||
120 | static struct rockchip_pll_clock rk3188_pll_clks[] __initdata = { | ||
121 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK2928_PLL_CON(0), | ||
122 | RK2928_MODE_CON, 0, 6, rk3188_pll_rates), | ||
123 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK2928_PLL_CON(4), | ||
124 | RK2928_MODE_CON, 4, 5, NULL), | ||
125 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK2928_PLL_CON(8), | ||
126 | RK2928_MODE_CON, 8, 7, rk3188_pll_rates), | ||
127 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK2928_PLL_CON(12), | ||
128 | RK2928_MODE_CON, 12, 8, rk3188_pll_rates), | ||
129 | }; | ||
130 | |||
131 | #define MFLAGS CLK_MUX_HIWORD_MASK | ||
132 | #define DFLAGS CLK_DIVIDER_HIWORD_MASK | ||
133 | #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) | ||
134 | |||
135 | /* 2 ^ (val + 1) */ | ||
136 | static struct clk_div_table div_core_peri_t[] = { | ||
137 | { .val = 0, .div = 2 }, | ||
138 | { .val = 1, .div = 4 }, | ||
139 | { .val = 2, .div = 8 }, | ||
140 | { .val = 3, .div = 16 }, | ||
141 | { /* sentinel */ }, | ||
142 | }; | ||
143 | |||
144 | static struct rockchip_clk_branch common_clk_branches[] __initdata = { | ||
145 | /* | ||
146 | * Clock-Architecture Diagram 2 | ||
147 | */ | ||
148 | |||
149 | GATE(0, "gpll_armclk", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS), | ||
150 | |||
151 | /* these two are set by the cpuclk and should not be changed */ | ||
152 | COMPOSITE_NOMUX_DIVTBL(CORE_PERI, "core_peri", "armclk", 0, | ||
153 | RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
154 | div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), | ||
155 | |||
156 | COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, | ||
157 | RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
158 | RK2928_CLKGATE_CON(3), 9, GFLAGS), | ||
159 | GATE(0, "hclk_vepu", "aclk_vepu", 0, | ||
160 | RK2928_CLKGATE_CON(3), 10, GFLAGS), | ||
161 | COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, | ||
162 | RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
163 | RK2928_CLKGATE_CON(3), 11, GFLAGS), | ||
164 | GATE(0, "hclk_vdpu", "aclk_vdpu", 0, | ||
165 | RK2928_CLKGATE_CON(3), 12, GFLAGS), | ||
166 | |||
167 | GATE(0, "gpll_ddr", "gpll", 0, | ||
168 | RK2928_CLKGATE_CON(1), 7, GFLAGS), | ||
169 | COMPOSITE(0, "ddrphy", mux_ddrphy_p, 0, | ||
170 | RK2928_CLKSEL_CON(26), 8, 1, MFLAGS, 0, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
171 | RK2928_CLKGATE_CON(0), 2, GFLAGS), | ||
172 | |||
173 | GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, | ||
174 | RK2928_CLKGATE_CON(0), 3, GFLAGS), | ||
175 | |||
176 | DIV(0, "pclk_cpu_pre", "aclk_cpu_pre", 0, | ||
177 | RK2928_CLKSEL_CON(1), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), | ||
178 | GATE(0, "atclk_cpu", "pclk_cpu_pre", 0, | ||
179 | RK2928_CLKGATE_CON(0), 6, GFLAGS), | ||
180 | GATE(0, "pclk_cpu", "pclk_cpu_pre", 0, | ||
181 | RK2928_CLKGATE_CON(0), 5, GFLAGS), | ||
182 | DIV(0, "hclk_cpu_pre", "aclk_cpu_pre", 0, | ||
183 | RK2928_CLKSEL_CON(1), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO), | ||
184 | COMPOSITE_NOMUX(0, "hclk_ahb2apb", "hclk_cpu_pre", 0, | ||
185 | RK2928_CLKSEL_CON(1), 14, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
186 | RK2928_CLKGATE_CON(4), 9, GFLAGS), | ||
187 | GATE(0, "hclk_cpu", "hclk_cpu_pre", 0, | ||
188 | RK2928_CLKGATE_CON(0), 4, GFLAGS), | ||
189 | |||
190 | COMPOSITE(0, "aclk_lcdc0_pre", mux_pll_src_cpll_gpll_p, 0, | ||
191 | RK2928_CLKSEL_CON(31), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
192 | RK2928_CLKGATE_CON(3), 0, GFLAGS), | ||
193 | COMPOSITE(0, "aclk_lcdc1_pre", mux_pll_src_cpll_gpll_p, 0, | ||
194 | RK2928_CLKSEL_CON(31), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
195 | RK2928_CLKGATE_CON(1), 4, GFLAGS), | ||
196 | |||
197 | GATE(0, "aclk_peri", "aclk_peri_pre", 0, | ||
198 | RK2928_CLKGATE_CON(2), 1, GFLAGS), | ||
199 | COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_pre", 0, | ||
200 | RK2928_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
201 | RK2928_CLKGATE_CON(2), 2, GFLAGS), | ||
202 | COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_pre", 0, | ||
203 | RK2928_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
204 | RK2928_CLKGATE_CON(2), 3, GFLAGS), | ||
205 | |||
206 | MUX(0, "cif_src", mux_pll_src_cpll_gpll_p, 0, | ||
207 | RK2928_CLKSEL_CON(29), 0, 1, MFLAGS), | ||
208 | COMPOSITE_NOMUX(0, "cif0_pre", "cif_src", 0, | ||
209 | RK2928_CLKSEL_CON(29), 1, 5, DFLAGS, | ||
210 | RK2928_CLKGATE_CON(3), 7, GFLAGS), | ||
211 | MUX(SCLK_CIF0, "sclk_cif0", mux_sclk_cif0_p, 0, | ||
212 | RK2928_CLKSEL_CON(29), 7, 1, MFLAGS), | ||
213 | |||
214 | GATE(0, "pclkin_cif0", "ext_cif0", 0, | ||
215 | RK2928_CLKGATE_CON(3), 3, GFLAGS), | ||
216 | |||
217 | /* | ||
218 | * the 480m are generated inside the usb block from these clocks, | ||
219 | * but they are also a source for the hsicphy clock. | ||
220 | */ | ||
221 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0, | ||
222 | RK2928_CLKGATE_CON(1), 5, GFLAGS), | ||
223 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0, | ||
224 | RK2928_CLKGATE_CON(1), 6, GFLAGS), | ||
225 | |||
226 | COMPOSITE(0, "mac_src", mux_mac_p, 0, | ||
227 | RK2928_CLKSEL_CON(21), 0, 1, MFLAGS, 8, 5, DFLAGS, | ||
228 | RK2928_CLKGATE_CON(2), 5, GFLAGS), | ||
229 | MUX(SCLK_MAC, "sclk_macref", mux_sclk_macref_p, CLK_SET_RATE_PARENT, | ||
230 | RK2928_CLKSEL_CON(21), 4, 1, MFLAGS), | ||
231 | GATE(0, "sclk_mac_lbtest", "sclk_macref", | ||
232 | RK2928_CLKGATE_CON(2), 12, 0, GFLAGS), | ||
233 | |||
234 | COMPOSITE(0, "hsadc_src", mux_pll_src_gpll_cpll_p, 0, | ||
235 | RK2928_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
236 | RK2928_CLKGATE_CON(2), 6, GFLAGS), | ||
237 | COMPOSITE_FRAC(0, "hsadc_frac", "hsadc_src", | ||
238 | RK2928_CLKSEL_CON(23), 0, | ||
239 | RK2928_CLKGATE_CON(2), 7, 0, GFLAGS), | ||
240 | MUX(SCLK_HSADC, "sclk_hsadc", mux_sclk_hsadc_p, 0, | ||
241 | RK2928_CLKSEL_CON(22), 4, 2, MFLAGS), | ||
242 | |||
243 | COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, | ||
244 | RK2928_CLKSEL_CON(24), 8, 8, DFLAGS, | ||
245 | RK2928_CLKGATE_CON(2), 8, GFLAGS), | ||
246 | |||
247 | /* | ||
248 | * Clock-Architecture Diagram 4 | ||
249 | */ | ||
250 | |||
251 | GATE(SCLK_SMC, "sclk_smc", "hclk_peri", | ||
252 | RK2928_CLKGATE_CON(2), 4, 0, GFLAGS), | ||
253 | |||
254 | COMPOSITE_NOMUX(SCLK_SPI0, "sclk_spi0", "pclk_peri", 0, | ||
255 | RK2928_CLKSEL_CON(25), 0, 7, DFLAGS, | ||
256 | RK2928_CLKGATE_CON(2), 9, GFLAGS), | ||
257 | COMPOSITE_NOMUX(SCLK_SPI1, "sclk_spi1", "pclk_peri", 0, | ||
258 | RK2928_CLKSEL_CON(25), 8, 7, DFLAGS, | ||
259 | RK2928_CLKGATE_CON(2), 10, GFLAGS), | ||
260 | |||
261 | COMPOSITE_NOMUX(SCLK_SDMMC, "sclk_sdmmc", "hclk_peri", 0, | ||
262 | RK2928_CLKSEL_CON(11), 0, 6, DFLAGS, | ||
263 | RK2928_CLKGATE_CON(2), 11, GFLAGS), | ||
264 | COMPOSITE_NOMUX(SCLK_SDIO, "sclk_sdio", "hclk_peri", 0, | ||
265 | RK2928_CLKSEL_CON(12), 0, 6, DFLAGS, | ||
266 | RK2928_CLKGATE_CON(2), 13, GFLAGS), | ||
267 | COMPOSITE_NOMUX(SCLK_EMMC, "sclk_emmc", "hclk_peri", 0, | ||
268 | RK2928_CLKSEL_CON(12), 8, 6, DFLAGS, | ||
269 | RK2928_CLKGATE_CON(2), 14, GFLAGS), | ||
270 | |||
271 | MUX(0, "uart_src", mux_pll_src_gpll_cpll_p, 0, | ||
272 | RK2928_CLKSEL_CON(12), 15, 1, MFLAGS), | ||
273 | COMPOSITE_NOMUX(0, "uart0_pre", "uart_src", 0, | ||
274 | RK2928_CLKSEL_CON(13), 0, 7, DFLAGS, | ||
275 | RK2928_CLKGATE_CON(1), 8, GFLAGS), | ||
276 | COMPOSITE_FRAC(0, "uart0_frac", "uart0_pre", 0, | ||
277 | RK2928_CLKSEL_CON(17), 0, | ||
278 | RK2928_CLKGATE_CON(1), 9, GFLAGS), | ||
279 | MUX(SCLK_UART0, "sclk_uart0", mux_sclk_uart0_p, 0, | ||
280 | RK2928_CLKSEL_CON(13), 8, 2, MFLAGS), | ||
281 | COMPOSITE_NOMUX(0, "uart1_pre", "uart_src", 0, | ||
282 | RK2928_CLKSEL_CON(14), 0, 7, DFLAGS, | ||
283 | RK2928_CLKGATE_CON(1), 10, GFLAGS), | ||
284 | COMPOSITE_FRAC(0, "uart1_frac", "uart1_pre", 0, | ||
285 | RK2928_CLKSEL_CON(18), 0, | ||
286 | RK2928_CLKGATE_CON(1), 11, GFLAGS), | ||
287 | MUX(SCLK_UART1, "sclk_uart1", mux_sclk_uart1_p, 0, | ||
288 | RK2928_CLKSEL_CON(14), 8, 2, MFLAGS), | ||
289 | COMPOSITE_NOMUX(0, "uart2_pre", "uart_src", 0, | ||
290 | RK2928_CLKSEL_CON(15), 0, 7, DFLAGS, | ||
291 | RK2928_CLKGATE_CON(1), 12, GFLAGS), | ||
292 | COMPOSITE_FRAC(0, "uart2_frac", "uart2_pre", 0, | ||
293 | RK2928_CLKSEL_CON(19), 0, | ||
294 | RK2928_CLKGATE_CON(1), 13, GFLAGS), | ||
295 | MUX(SCLK_UART2, "sclk_uart2", mux_sclk_uart2_p, 0, | ||
296 | RK2928_CLKSEL_CON(15), 8, 2, MFLAGS), | ||
297 | COMPOSITE_NOMUX(0, "uart3_pre", "uart_src", 0, | ||
298 | RK2928_CLKSEL_CON(16), 0, 7, DFLAGS, | ||
299 | RK2928_CLKGATE_CON(1), 14, GFLAGS), | ||
300 | COMPOSITE_FRAC(0, "uart3_frac", "uart3_pre", 0, | ||
301 | RK2928_CLKSEL_CON(20), 0, | ||
302 | RK2928_CLKGATE_CON(1), 15, GFLAGS), | ||
303 | MUX(SCLK_UART3, "sclk_uart3", mux_sclk_uart3_p, 0, | ||
304 | RK2928_CLKSEL_CON(16), 8, 2, MFLAGS), | ||
305 | |||
306 | GATE(SCLK_JTAG, "jtag", "ext_jtag", 0, RK2928_CLKGATE_CON(1), 3, GFLAGS), | ||
307 | |||
308 | GATE(SCLK_TIMER0, "timer0", "xin24m", 0, RK2928_CLKGATE_CON(1), 0, GFLAGS), | ||
309 | GATE(SCLK_TIMER1, "timer1", "xin24m", 0, RK2928_CLKGATE_CON(1), 1, GFLAGS), | ||
310 | |||
311 | /* clk_core_pre gates */ | ||
312 | GATE(0, "core_dbg", "armclk", 0, RK2928_CLKGATE_CON(9), 0, GFLAGS), | ||
313 | |||
314 | /* aclk_cpu gates */ | ||
315 | GATE(ACLK_DMA1, "aclk_dma1", "aclk_cpu", 0, RK2928_CLKGATE_CON(5), 0, GFLAGS), | ||
316 | GATE(0, "aclk_intmem", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 12, GFLAGS), | ||
317 | GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK2928_CLKGATE_CON(4), 10, GFLAGS), | ||
318 | |||
319 | /* hclk_cpu gates */ | ||
320 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK2928_CLKGATE_CON(5), 6, GFLAGS), | ||
321 | GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 2, GFLAGS), | ||
322 | GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 1, GFLAGS), | ||
323 | GATE(0, "hclk_cpubus", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 8, GFLAGS), | ||
324 | /* hclk_ahb2apb is part of a clk branch */ | ||
325 | GATE(0, "hclk_vio_bus", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 12, GFLAGS), | ||
326 | GATE(HCLK_LCDC0, "hclk_lcdc0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 1, GFLAGS), | ||
327 | GATE(HCLK_LCDC1, "hclk_lcdc1", "aclk_cpu", 0, RK2928_CLKGATE_CON(6), 2, GFLAGS), | ||
328 | GATE(HCLK_CIF0, "hclk_cif0", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 4, GFLAGS), | ||
329 | GATE(HCLK_IPP, "hclk_ipp", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 9, GFLAGS), | ||
330 | GATE(HCLK_RGA, "hclk_rga", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 10, GFLAGS), | ||
331 | |||
332 | /* hclk_peri gates */ | ||
333 | GATE(0, "hclk_peri_axi_matrix", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 0, GFLAGS), | ||
334 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 6, GFLAGS), | ||
335 | GATE(0, "hclk_emem_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 7, GFLAGS), | ||
336 | GATE(HCLK_EMAC, "hclk_emac", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 0, GFLAGS), | ||
337 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 9, GFLAGS), | ||
338 | GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK2928_CLKGATE_CON(4), 5, GFLAGS), | ||
339 | GATE(HCLK_OTG0, "hclk_usbotg0", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 13, GFLAGS), | ||
340 | GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 5, GFLAGS), | ||
341 | GATE(HCLK_PIDF, "hclk_pidfilter", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 6, GFLAGS), | ||
342 | GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 10, GFLAGS), | ||
343 | GATE(HCLK_SDIO, "hclk_sdio", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 11, GFLAGS), | ||
344 | GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 12, GFLAGS), | ||
345 | |||
346 | /* aclk_lcdc0_pre gates */ | ||
347 | GATE(0, "aclk_vio0", "aclk_lcdc0_pre", 0, RK2928_CLKGATE_CON(6), 13, GFLAGS), | ||
348 | GATE(ACLK_LCDC0, "aclk_lcdc0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 0, GFLAGS), | ||
349 | GATE(ACLK_CIF0, "aclk_cif0", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 5, GFLAGS), | ||
350 | GATE(ACLK_IPP, "aclk_ipp", "aclk_vio0", 0, RK2928_CLKGATE_CON(6), 8, GFLAGS), | ||
351 | |||
352 | /* aclk_lcdc1_pre gates */ | ||
353 | GATE(0, "aclk_vio1", "aclk_lcdc1_pre", 0, RK2928_CLKGATE_CON(9), 5, GFLAGS), | ||
354 | GATE(ACLK_LCDC1, "aclk_lcdc1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 3, GFLAGS), | ||
355 | GATE(ACLK_RGA, "aclk_rga", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 11, GFLAGS), | ||
356 | |||
357 | /* atclk_cpu gates */ | ||
358 | GATE(0, "atclk", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 3, GFLAGS), | ||
359 | GATE(0, "trace", "atclk_cpu", 0, RK2928_CLKGATE_CON(9), 2, GFLAGS), | ||
360 | |||
361 | /* pclk_cpu gates */ | ||
362 | GATE(PCLK_PWM01, "pclk_pwm01", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 10, GFLAGS), | ||
363 | GATE(PCLK_TIMER0, "pclk_timer0", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 7, GFLAGS), | ||
364 | GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 4, GFLAGS), | ||
365 | GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 5, GFLAGS), | ||
366 | GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 9, GFLAGS), | ||
367 | GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 10, GFLAGS), | ||
368 | GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 11, GFLAGS), | ||
369 | GATE(PCLK_EFUSE, "pclk_efuse", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 2, GFLAGS), | ||
370 | GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 3, GFLAGS), | ||
371 | GATE(0, "pclk_ddrupctl", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 7, GFLAGS), | ||
372 | GATE(0, "pclk_ddrpubl", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 6, GFLAGS), | ||
373 | GATE(0, "pclk_dbg", "pclk_cpu", 0, RK2928_CLKGATE_CON(9), 1, GFLAGS), | ||
374 | GATE(PCLK_GRF, "pclk_grf", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 4, GFLAGS), | ||
375 | GATE(PCLK_PMU, "pclk_pmu", "pclk_cpu", 0, RK2928_CLKGATE_CON(5), 5, GFLAGS), | ||
376 | |||
377 | /* aclk_peri */ | ||
378 | GATE(ACLK_DMA2, "aclk_dma2", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 1, GFLAGS), | ||
379 | GATE(ACLK_SMC, "aclk_smc", "aclk_peri", 0, RK2928_CLKGATE_CON(5), 8, GFLAGS), | ||
380 | GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 4, GFLAGS), | ||
381 | GATE(0, "aclk_cpu_peri", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 2, GFLAGS), | ||
382 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK2928_CLKGATE_CON(4), 3, GFLAGS), | ||
383 | |||
384 | /* pclk_peri gates */ | ||
385 | GATE(0, "pclk_peri_axi_matrix", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 1, GFLAGS), | ||
386 | GATE(PCLK_PWM23, "pclk_pwm23", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 11, GFLAGS), | ||
387 | GATE(PCLK_WDT, "pclk_wdt", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 15, GFLAGS), | ||
388 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 12, GFLAGS), | ||
389 | GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 13, GFLAGS), | ||
390 | GATE(PCLK_UART2, "pclk_uart2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 2, GFLAGS), | ||
391 | GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 3, GFLAGS), | ||
392 | GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 6, GFLAGS), | ||
393 | GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 7, GFLAGS), | ||
394 | GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 8, GFLAGS), | ||
395 | GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 12, GFLAGS), | ||
396 | GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK2928_CLKGATE_CON(7), 14, GFLAGS), | ||
397 | }; | ||
398 | |||
399 | PNAME(mux_rk3066_lcdc0_p) = { "dclk_lcdc0_src", "xin27m" }; | ||
400 | PNAME(mux_rk3066_lcdc1_p) = { "dclk_lcdc1_src", "xin27m" }; | ||
401 | PNAME(mux_sclk_cif1_p) = { "cif1_pre", "xin24m" }; | ||
402 | PNAME(mux_sclk_i2s1_p) = { "i2s1_pre", "i2s1_frac", "xin12m" }; | ||
403 | PNAME(mux_sclk_i2s2_p) = { "i2s2_pre", "i2s2_frac", "xin12m" }; | ||
404 | |||
405 | static struct clk_div_table div_aclk_cpu_t[] = { | ||
406 | { .val = 0, .div = 1 }, | ||
407 | { .val = 1, .div = 2 }, | ||
408 | { .val = 2, .div = 3 }, | ||
409 | { .val = 3, .div = 4 }, | ||
410 | { .val = 4, .div = 8 }, | ||
411 | { /* sentinel */ }, | ||
412 | }; | ||
413 | |||
414 | static struct rockchip_clk_branch rk3066a_clk_branches[] __initdata = { | ||
415 | COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0, | ||
416 | RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 0, 5, DFLAGS), | ||
417 | DIVTBL(0, "aclk_cpu_pre", "armclk", 0, | ||
418 | RK2928_CLKSEL_CON(1), 0, 3, DFLAGS, div_aclk_cpu_t), | ||
419 | |||
420 | GATE(CORE_L2C, "core_l2c", "aclk_cpu", 0, | ||
421 | RK2928_CLKGATE_CON(9), 4, GFLAGS), | ||
422 | |||
423 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_gpll_cpll_p, 0, | ||
424 | RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, | ||
425 | RK2928_CLKGATE_CON(2), 0, GFLAGS), | ||
426 | |||
427 | COMPOSITE(0, "dclk_lcdc0_src", mux_pll_src_cpll_gpll_p, 0, | ||
428 | RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
429 | RK2928_CLKGATE_CON(3), 1, GFLAGS), | ||
430 | MUX(DCLK_LCDC0, "dclk_lcdc0", mux_rk3066_lcdc0_p, 0, | ||
431 | RK2928_CLKSEL_CON(27), 4, 1, MFLAGS), | ||
432 | COMPOSITE(0, "dclk_lcdc1_src", mux_pll_src_cpll_gpll_p, 0, | ||
433 | RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
434 | RK2928_CLKGATE_CON(3), 2, GFLAGS), | ||
435 | MUX(DCLK_LCDC1, "dclk_lcdc1", mux_rk3066_lcdc1_p, 0, | ||
436 | RK2928_CLKSEL_CON(28), 4, 1, MFLAGS), | ||
437 | |||
438 | COMPOSITE_NOMUX(0, "cif1_pre", "cif_src", 0, | ||
439 | RK2928_CLKSEL_CON(29), 8, 5, DFLAGS, | ||
440 | RK2928_CLKGATE_CON(3), 8, GFLAGS), | ||
441 | MUX(SCLK_CIF1, "sclk_cif1", mux_sclk_cif1_p, 0, | ||
442 | RK2928_CLKSEL_CON(29), 15, 1, MFLAGS), | ||
443 | |||
444 | GATE(0, "pclkin_cif1", "ext_cif1", 0, | ||
445 | RK2928_CLKGATE_CON(3), 4, GFLAGS), | ||
446 | |||
447 | COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0, | ||
448 | RK2928_CLKSEL_CON(33), 8, 1, MFLAGS, 0, 5, DFLAGS, | ||
449 | RK2928_CLKGATE_CON(3), 13, GFLAGS), | ||
450 | GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0, | ||
451 | RK2928_CLKGATE_CON(5), 15, GFLAGS), | ||
452 | |||
453 | GATE(SCLK_TIMER2, "timer2", "xin24m", 0, | ||
454 | RK2928_CLKGATE_CON(3), 2, GFLAGS), | ||
455 | |||
456 | COMPOSITE_NOMUX(0, "sclk_tsadc", "xin24m", 0, | ||
457 | RK2928_CLKSEL_CON(34), 0, 16, DFLAGS, | ||
458 | RK2928_CLKGATE_CON(2), 15, GFLAGS), | ||
459 | |||
460 | MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, | ||
461 | RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), | ||
462 | COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, | ||
463 | RK2928_CLKSEL_CON(2), 0, 7, DFLAGS, | ||
464 | RK2928_CLKGATE_CON(0), 7, GFLAGS), | ||
465 | COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, | ||
466 | RK2928_CLKSEL_CON(6), 0, | ||
467 | RK2928_CLKGATE_CON(0), 8, GFLAGS), | ||
468 | MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, | ||
469 | RK2928_CLKSEL_CON(2), 8, 2, MFLAGS), | ||
470 | COMPOSITE_NOMUX(0, "i2s1_pre", "i2s_src", 0, | ||
471 | RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, | ||
472 | RK2928_CLKGATE_CON(0), 9, GFLAGS), | ||
473 | COMPOSITE_FRAC(0, "i2s1_frac", "i2s1_pre", 0, | ||
474 | RK2928_CLKSEL_CON(7), 0, | ||
475 | RK2928_CLKGATE_CON(0), 10, GFLAGS), | ||
476 | MUX(SCLK_I2S1, "sclk_i2s1", mux_sclk_i2s1_p, 0, | ||
477 | RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), | ||
478 | COMPOSITE_NOMUX(0, "i2s2_pre", "i2s_src", 0, | ||
479 | RK2928_CLKSEL_CON(4), 0, 7, DFLAGS, | ||
480 | RK2928_CLKGATE_CON(0), 11, GFLAGS), | ||
481 | COMPOSITE_FRAC(0, "i2s2_frac", "i2s2_pre", 0, | ||
482 | RK2928_CLKSEL_CON(8), 0, | ||
483 | RK2928_CLKGATE_CON(0), 12, GFLAGS), | ||
484 | MUX(SCLK_I2S2, "sclk_i2s2", mux_sclk_i2s2_p, 0, | ||
485 | RK2928_CLKSEL_CON(4), 8, 2, MFLAGS), | ||
486 | COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, | ||
487 | RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
488 | RK2928_CLKGATE_CON(0), 13, GFLAGS), | ||
489 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, | ||
490 | RK2928_CLKSEL_CON(9), 0, | ||
491 | RK2928_CLKGATE_CON(0), 14, GFLAGS), | ||
492 | MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, | ||
493 | RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), | ||
494 | |||
495 | GATE(HCLK_I2S1, "hclk_i2s1", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), | ||
496 | GATE(HCLK_I2S2, "hclk_i2s2", "hclk_cpu", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), | ||
497 | GATE(0, "hclk_cif1", "hclk_cpu", 0, RK2928_CLKGATE_CON(6), 6, GFLAGS), | ||
498 | GATE(0, "hclk_hdmi", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), | ||
499 | |||
500 | GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(5), 14, GFLAGS), | ||
501 | |||
502 | GATE(0, "aclk_cif1", "aclk_vio1", 0, RK2928_CLKGATE_CON(6), 7, GFLAGS), | ||
503 | |||
504 | GATE(PCLK_TIMER1, "pclk_timer1", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 8, GFLAGS), | ||
505 | GATE(PCLK_TIMER2, "pclk_timer2", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), | ||
506 | GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 15, GFLAGS), | ||
507 | GATE(PCLK_UART0, "pclk_uart0", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), | ||
508 | GATE(PCLK_UART1, "pclk_uart1", "pclk_cpu", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), | ||
509 | |||
510 | GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), | ||
511 | GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK2928_CLKGATE_CON(4), 13, GFLAGS), | ||
512 | }; | ||
513 | |||
514 | static struct clk_div_table div_rk3188_aclk_core_t[] = { | ||
515 | { .val = 0, .div = 1 }, | ||
516 | { .val = 1, .div = 2 }, | ||
517 | { .val = 2, .div = 3 }, | ||
518 | { .val = 3, .div = 4 }, | ||
519 | { .val = 4, .div = 8 }, | ||
520 | { /* sentinel */ }, | ||
521 | }; | ||
522 | |||
523 | PNAME(mux_hsicphy_p) = { "sclk_otgphy0", "sclk_otgphy1", | ||
524 | "gpll", "cpll" }; | ||
525 | |||
526 | static struct rockchip_clk_branch rk3188_clk_branches[] __initdata = { | ||
527 | COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0, | ||
528 | RK2928_CLKSEL_CON(0), 8, 1, MFLAGS, 9, 5, DFLAGS), | ||
529 | COMPOSITE_NOMUX_DIVTBL(0, "aclk_core", "armclk", 0, | ||
530 | RK2928_CLKSEL_CON(1), 3, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, | ||
531 | div_rk3188_aclk_core_t, RK2928_CLKGATE_CON(0), 7, GFLAGS), | ||
532 | |||
533 | /* do not source aclk_cpu_pre from the apll, to keep complexity down */ | ||
534 | COMPOSITE_NOGATE(0, "aclk_cpu_pre", mux_aclk_cpu_p, CLK_SET_RATE_NO_REPARENT, | ||
535 | RK2928_CLKSEL_CON(0), 5, 1, MFLAGS, 0, 5, DFLAGS), | ||
536 | |||
537 | GATE(CORE_L2C, "core_l2c", "armclk", 0, | ||
538 | RK2928_CLKGATE_CON(9), 4, GFLAGS), | ||
539 | |||
540 | COMPOSITE(0, "aclk_peri_pre", mux_pll_src_cpll_gpll_p, 0, | ||
541 | RK2928_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, | ||
542 | RK2928_CLKGATE_CON(2), 0, GFLAGS), | ||
543 | |||
544 | COMPOSITE(DCLK_LCDC0, "dclk_lcdc0", mux_pll_src_cpll_gpll_p, 0, | ||
545 | RK2928_CLKSEL_CON(27), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
546 | RK2928_CLKGATE_CON(3), 1, GFLAGS), | ||
547 | COMPOSITE(DCLK_LCDC1, "dclk_lcdc1", mux_pll_src_cpll_gpll_p, 0, | ||
548 | RK2928_CLKSEL_CON(28), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
549 | RK2928_CLKGATE_CON(3), 2, GFLAGS), | ||
550 | |||
551 | COMPOSITE(0, "aclk_gpu_src", mux_pll_src_cpll_gpll_p, 0, | ||
552 | RK2928_CLKSEL_CON(34), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
553 | RK2928_CLKGATE_CON(3), 15, GFLAGS), | ||
554 | GATE(ACLK_GPU, "aclk_gpu", "aclk_gpu_src", 0, | ||
555 | RK2928_CLKGATE_CON(9), 7, GFLAGS), | ||
556 | |||
557 | GATE(SCLK_TIMER2, "timer2", "xin24m", 0, RK2928_CLKGATE_CON(3), 4, GFLAGS), | ||
558 | GATE(SCLK_TIMER3, "timer3", "xin24m", 0, RK2928_CLKGATE_CON(1), 2, GFLAGS), | ||
559 | GATE(SCLK_TIMER4, "timer4", "xin24m", 0, RK2928_CLKGATE_CON(3), 5, GFLAGS), | ||
560 | GATE(SCLK_TIMER5, "timer5", "xin24m", 0, RK2928_CLKGATE_CON(3), 8, GFLAGS), | ||
561 | GATE(SCLK_TIMER6, "timer6", "xin24m", 0, RK2928_CLKGATE_CON(3), 14, GFLAGS), | ||
562 | |||
563 | COMPOSITE_NODIV(0, "sclk_hsicphy_480m", mux_hsicphy_p, 0, | ||
564 | RK2928_CLKSEL_CON(30), 0, 2, DFLAGS, | ||
565 | RK2928_CLKGATE_CON(3), 6, GFLAGS), | ||
566 | DIV(0, "sclk_hsicphy_12m", "sclk_hsicphy_480m", 0, | ||
567 | RK2928_CLKGATE_CON(11), 8, 6, DFLAGS), | ||
568 | |||
569 | MUX(0, "i2s_src", mux_pll_src_gpll_cpll_p, 0, | ||
570 | RK2928_CLKSEL_CON(2), 15, 1, MFLAGS), | ||
571 | COMPOSITE_NOMUX(0, "i2s0_pre", "i2s_src", 0, | ||
572 | RK2928_CLKSEL_CON(3), 0, 7, DFLAGS, | ||
573 | RK2928_CLKGATE_CON(0), 9, GFLAGS), | ||
574 | COMPOSITE_FRAC(0, "i2s0_frac", "i2s0_pre", 0, | ||
575 | RK2928_CLKSEL_CON(7), 0, | ||
576 | RK2928_CLKGATE_CON(0), 10, GFLAGS), | ||
577 | MUX(SCLK_I2S0, "sclk_i2s0", mux_sclk_i2s0_p, 0, | ||
578 | RK2928_CLKSEL_CON(3), 8, 2, MFLAGS), | ||
579 | COMPOSITE_NOMUX(0, "spdif_pre", "i2s_src", 0, | ||
580 | RK2928_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
581 | RK2928_CLKGATE_CON(13), 13, GFLAGS), | ||
582 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_pll", 0, | ||
583 | RK2928_CLKSEL_CON(9), 0, | ||
584 | RK2928_CLKGATE_CON(0), 14, GFLAGS), | ||
585 | MUX(SCLK_SPDIF, "sclk_spdif", mux_sclk_spdif_p, 0, | ||
586 | RK2928_CLKSEL_CON(5), 8, 2, MFLAGS), | ||
587 | |||
588 | GATE(0, "hclk_imem0", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 14, GFLAGS), | ||
589 | GATE(0, "hclk_imem1", "hclk_cpu", 0, RK2928_CLKGATE_CON(4), 15, GFLAGS), | ||
590 | |||
591 | GATE(HCLK_OTG1, "hclk_usbotg1", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 3, GFLAGS), | ||
592 | GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK2928_CLKGATE_CON(7), 4, GFLAGS), | ||
593 | |||
594 | GATE(PCLK_TIMER3, "pclk_timer3", "pclk_cpu", 0, RK2928_CLKGATE_CON(7), 9, GFLAGS), | ||
595 | |||
596 | GATE(PCLK_UART0, "pclk_uart0", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 0, GFLAGS), | ||
597 | GATE(PCLK_UART1, "pclk_uart1", "hclk_ahb2apb", 0, RK2928_CLKGATE_CON(8), 1, GFLAGS), | ||
598 | |||
599 | GATE(ACLK_GPS, "aclk_gps", "aclk_peri", 0, RK2928_CLKGATE_CON(8), 13, GFLAGS), | ||
600 | }; | ||
601 | |||
602 | static void __init rk3188_common_clk_init(struct device_node *np) | ||
603 | { | ||
604 | void __iomem *reg_base; | ||
605 | struct clk *clk; | ||
606 | |||
607 | reg_base = of_iomap(np, 0); | ||
608 | if (!reg_base) { | ||
609 | pr_err("%s: could not map cru region\n", __func__); | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | ||
614 | |||
615 | /* xin12m is created by an cru-internal divider */ | ||
616 | clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); | ||
617 | if (IS_ERR(clk)) | ||
618 | pr_warn("%s: could not register clock xin12m: %ld\n", | ||
619 | __func__, PTR_ERR(clk)); | ||
620 | |||
621 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); | ||
622 | if (IS_ERR(clk)) | ||
623 | pr_warn("%s: could not register clock usb480m: %ld\n", | ||
624 | __func__, PTR_ERR(clk)); | ||
625 | |||
626 | rockchip_clk_register_plls(rk3188_pll_clks, | ||
627 | ARRAY_SIZE(rk3188_pll_clks), | ||
628 | RK3188_GRF_SOC_STATUS); | ||
629 | rockchip_clk_register_branches(common_clk_branches, | ||
630 | ARRAY_SIZE(common_clk_branches)); | ||
631 | |||
632 | rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), | ||
633 | ROCKCHIP_SOFTRST_HIWORD_MASK); | ||
634 | } | ||
635 | |||
636 | static void __init rk3066a_clk_init(struct device_node *np) | ||
637 | { | ||
638 | rk3188_common_clk_init(np); | ||
639 | rockchip_clk_register_branches(rk3066a_clk_branches, | ||
640 | ARRAY_SIZE(rk3066a_clk_branches)); | ||
641 | } | ||
642 | CLK_OF_DECLARE(rk3066a_cru, "rockchip,rk3066a-cru", rk3066a_clk_init); | ||
643 | |||
644 | static void __init rk3188a_clk_init(struct device_node *np) | ||
645 | { | ||
646 | rk3188_common_clk_init(np); | ||
647 | rockchip_clk_register_branches(rk3188_clk_branches, | ||
648 | ARRAY_SIZE(rk3188_clk_branches)); | ||
649 | } | ||
650 | CLK_OF_DECLARE(rk3188a_cru, "rockchip,rk3188a-cru", rk3188a_clk_init); | ||
651 | |||
652 | static void __init rk3188_clk_init(struct device_node *np) | ||
653 | { | ||
654 | int i; | ||
655 | |||
656 | for (i = 0; i < ARRAY_SIZE(rk3188_pll_clks); i++) { | ||
657 | struct rockchip_pll_clock *pll = &rk3188_pll_clks[i]; | ||
658 | struct rockchip_pll_rate_table *rate; | ||
659 | |||
660 | if (!pll->rate_table) | ||
661 | continue; | ||
662 | |||
663 | rate = pll->rate_table; | ||
664 | while (rate->rate > 0) { | ||
665 | rate->bwadj = 0; | ||
666 | rate++; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | rk3188a_clk_init(np); | ||
671 | } | ||
672 | CLK_OF_DECLARE(rk3188_cru, "rockchip,rk3188-cru", rk3188_clk_init); | ||
diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c new file mode 100644 index 000000000000..0d8c6c59a75e --- /dev/null +++ b/drivers/clk/rockchip/clk-rk3288.c | |||
@@ -0,0 +1,717 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/clk-provider.h> | ||
17 | #include <linux/of.h> | ||
18 | #include <linux/of_address.h> | ||
19 | #include <dt-bindings/clock/rk3288-cru.h> | ||
20 | #include "clk.h" | ||
21 | |||
22 | #define RK3288_GRF_SOC_CON(x) (0x244 + x * 4) | ||
23 | #define RK3288_GRF_SOC_STATUS 0x280 | ||
24 | |||
25 | enum rk3288_plls { | ||
26 | apll, dpll, cpll, gpll, npll, | ||
27 | }; | ||
28 | |||
29 | struct rockchip_pll_rate_table rk3288_pll_rates[] = { | ||
30 | RK3066_PLL_RATE(2208000000, 1, 92, 1), | ||
31 | RK3066_PLL_RATE(2184000000, 1, 91, 1), | ||
32 | RK3066_PLL_RATE(2160000000, 1, 90, 1), | ||
33 | RK3066_PLL_RATE(2136000000, 1, 89, 1), | ||
34 | RK3066_PLL_RATE(2112000000, 1, 88, 1), | ||
35 | RK3066_PLL_RATE(2088000000, 1, 87, 1), | ||
36 | RK3066_PLL_RATE(2064000000, 1, 86, 1), | ||
37 | RK3066_PLL_RATE(2040000000, 1, 85, 1), | ||
38 | RK3066_PLL_RATE(2016000000, 1, 84, 1), | ||
39 | RK3066_PLL_RATE(1992000000, 1, 83, 1), | ||
40 | RK3066_PLL_RATE(1968000000, 1, 82, 1), | ||
41 | RK3066_PLL_RATE(1944000000, 1, 81, 1), | ||
42 | RK3066_PLL_RATE(1920000000, 1, 80, 1), | ||
43 | RK3066_PLL_RATE(1896000000, 1, 79, 1), | ||
44 | RK3066_PLL_RATE(1872000000, 1, 78, 1), | ||
45 | RK3066_PLL_RATE(1848000000, 1, 77, 1), | ||
46 | RK3066_PLL_RATE(1824000000, 1, 76, 1), | ||
47 | RK3066_PLL_RATE(1800000000, 1, 75, 1), | ||
48 | RK3066_PLL_RATE(1776000000, 1, 74, 1), | ||
49 | RK3066_PLL_RATE(1752000000, 1, 73, 1), | ||
50 | RK3066_PLL_RATE(1728000000, 1, 72, 1), | ||
51 | RK3066_PLL_RATE(1704000000, 1, 71, 1), | ||
52 | RK3066_PLL_RATE(1680000000, 1, 70, 1), | ||
53 | RK3066_PLL_RATE(1656000000, 1, 69, 1), | ||
54 | RK3066_PLL_RATE(1632000000, 1, 68, 1), | ||
55 | RK3066_PLL_RATE(1608000000, 1, 67, 1), | ||
56 | RK3066_PLL_RATE(1560000000, 1, 65, 1), | ||
57 | RK3066_PLL_RATE(1512000000, 1, 63, 1), | ||
58 | RK3066_PLL_RATE(1488000000, 1, 62, 1), | ||
59 | RK3066_PLL_RATE(1464000000, 1, 61, 1), | ||
60 | RK3066_PLL_RATE(1440000000, 1, 60, 1), | ||
61 | RK3066_PLL_RATE(1416000000, 1, 59, 1), | ||
62 | RK3066_PLL_RATE(1392000000, 1, 58, 1), | ||
63 | RK3066_PLL_RATE(1368000000, 1, 57, 1), | ||
64 | RK3066_PLL_RATE(1344000000, 1, 56, 1), | ||
65 | RK3066_PLL_RATE(1320000000, 1, 55, 1), | ||
66 | RK3066_PLL_RATE(1296000000, 1, 54, 1), | ||
67 | RK3066_PLL_RATE(1272000000, 1, 53, 1), | ||
68 | RK3066_PLL_RATE(1248000000, 1, 52, 1), | ||
69 | RK3066_PLL_RATE(1224000000, 1, 51, 1), | ||
70 | RK3066_PLL_RATE(1200000000, 1, 50, 1), | ||
71 | RK3066_PLL_RATE(1188000000, 2, 99, 1), | ||
72 | RK3066_PLL_RATE(1176000000, 1, 49, 1), | ||
73 | RK3066_PLL_RATE(1128000000, 1, 47, 1), | ||
74 | RK3066_PLL_RATE(1104000000, 1, 46, 1), | ||
75 | RK3066_PLL_RATE(1008000000, 1, 84, 2), | ||
76 | RK3066_PLL_RATE( 912000000, 1, 76, 2), | ||
77 | RK3066_PLL_RATE( 891000000, 8, 594, 2), | ||
78 | RK3066_PLL_RATE( 888000000, 1, 74, 2), | ||
79 | RK3066_PLL_RATE( 816000000, 1, 68, 2), | ||
80 | RK3066_PLL_RATE( 798000000, 2, 133, 2), | ||
81 | RK3066_PLL_RATE( 792000000, 1, 66, 2), | ||
82 | RK3066_PLL_RATE( 768000000, 1, 64, 2), | ||
83 | RK3066_PLL_RATE( 742500000, 8, 495, 2), | ||
84 | RK3066_PLL_RATE( 696000000, 1, 58, 2), | ||
85 | RK3066_PLL_RATE( 600000000, 1, 50, 2), | ||
86 | RK3066_PLL_RATE( 594000000, 2, 198, 4), | ||
87 | RK3066_PLL_RATE( 552000000, 1, 46, 2), | ||
88 | RK3066_PLL_RATE( 504000000, 1, 84, 4), | ||
89 | RK3066_PLL_RATE( 456000000, 1, 76, 4), | ||
90 | RK3066_PLL_RATE( 408000000, 1, 68, 4), | ||
91 | RK3066_PLL_RATE( 384000000, 2, 128, 4), | ||
92 | RK3066_PLL_RATE( 360000000, 1, 60, 4), | ||
93 | RK3066_PLL_RATE( 312000000, 1, 52, 4), | ||
94 | RK3066_PLL_RATE( 300000000, 1, 50, 4), | ||
95 | RK3066_PLL_RATE( 297000000, 2, 198, 8), | ||
96 | RK3066_PLL_RATE( 252000000, 1, 84, 8), | ||
97 | RK3066_PLL_RATE( 216000000, 1, 72, 8), | ||
98 | RK3066_PLL_RATE( 148500000, 2, 99, 8), | ||
99 | RK3066_PLL_RATE( 126000000, 1, 84, 16), | ||
100 | RK3066_PLL_RATE( 48000000, 1, 64, 32), | ||
101 | { /* sentinel */ }, | ||
102 | }; | ||
103 | |||
104 | PNAME(mux_pll_p) = { "xin24m", "xin32k" }; | ||
105 | PNAME(mux_armclk_p) = { "apll_core", "gpll_core" }; | ||
106 | PNAME(mux_ddrphy_p) = { "dpll_ddr", "gpll_ddr" }; | ||
107 | PNAME(mux_aclk_cpu_src_p) = { "cpll_aclk_cpu", "gpll_aclk_cpu" }; | ||
108 | |||
109 | PNAME(mux_pll_src_cpll_gpll_p) = { "cpll", "gpll" }; | ||
110 | PNAME(mux_pll_src_npll_cpll_gpll_p) = { "npll", "cpll", "gpll" }; | ||
111 | PNAME(mux_pll_src_cpll_gpll_npll_p) = { "cpll", "gpll", "npll" }; | ||
112 | PNAME(mux_pll_src_cpll_gpll_usb480m_p) = { "cpll", "gpll", "usb480m" }; | ||
113 | |||
114 | PNAME(mux_mmc_src_p) = { "cpll", "gpll", "xin24m", "xin24m" }; | ||
115 | PNAME(mux_i2s_pre_p) = { "i2s_src", "i2s_frac", "ext_i2s", "xin12m" }; | ||
116 | PNAME(mux_i2s_clkout_p) = { "i2s_pre", "xin12m" }; | ||
117 | PNAME(mux_spdif_p) = { "spdif_pre", "spdif_frac", "xin12m" }; | ||
118 | PNAME(mux_spdif_8ch_p) = { "spdif_8ch_pre", "spdif_8ch_frac", "xin12m" }; | ||
119 | PNAME(mux_uart0_pll_p) = { "cpll", "gpll", "usbphy_480m_src", "npll" }; | ||
120 | PNAME(mux_uart0_p) = { "uart0_src", "uart0_frac", "xin24m" }; | ||
121 | PNAME(mux_uart1_p) = { "uart1_src", "uart1_frac", "xin24m" }; | ||
122 | PNAME(mux_uart2_p) = { "uart2_src", "uart2_frac", "xin24m" }; | ||
123 | PNAME(mux_uart3_p) = { "uart3_src", "uart3_frac", "xin24m" }; | ||
124 | PNAME(mux_uart4_p) = { "uart4_src", "uart4_frac", "xin24m" }; | ||
125 | PNAME(mux_cif_out_p) = { "cif_src", "xin24m" }; | ||
126 | PNAME(mux_macref_p) = { "mac_src", "ext_gmac" }; | ||
127 | PNAME(mux_hsadcout_p) = { "hsadc_src", "ext_hsadc" }; | ||
128 | PNAME(mux_edp_24m_p) = { "ext_edp_24m", "xin24m" }; | ||
129 | PNAME(mux_tspout_p) = { "cpll", "gpll", "npll", "xin27m" }; | ||
130 | |||
131 | PNAME(mux_usbphy480m_p) = { "sclk_otgphy0", "sclk_otgphy1", | ||
132 | "sclk_otgphy2" }; | ||
133 | PNAME(mux_hsicphy480m_p) = { "cpll", "gpll", "usbphy480m_src" }; | ||
134 | PNAME(mux_hsicphy12m_p) = { "hsicphy12m_xin12m", "hsicphy12m_usbphy" }; | ||
135 | |||
136 | static struct rockchip_pll_clock rk3288_pll_clks[] __initdata = { | ||
137 | [apll] = PLL(pll_rk3066, PLL_APLL, "apll", mux_pll_p, 0, RK3288_PLL_CON(0), | ||
138 | RK3288_MODE_CON, 0, 6, rk3288_pll_rates), | ||
139 | [dpll] = PLL(pll_rk3066, PLL_DPLL, "dpll", mux_pll_p, 0, RK3288_PLL_CON(4), | ||
140 | RK3288_MODE_CON, 4, 5, NULL), | ||
141 | [cpll] = PLL(pll_rk3066, PLL_CPLL, "cpll", mux_pll_p, 0, RK3288_PLL_CON(8), | ||
142 | RK3288_MODE_CON, 8, 7, rk3288_pll_rates), | ||
143 | [gpll] = PLL(pll_rk3066, PLL_GPLL, "gpll", mux_pll_p, 0, RK3288_PLL_CON(12), | ||
144 | RK3288_MODE_CON, 12, 8, rk3288_pll_rates), | ||
145 | [npll] = PLL(pll_rk3066, PLL_NPLL, "npll", mux_pll_p, 0, RK3288_PLL_CON(16), | ||
146 | RK3288_MODE_CON, 14, 9, NULL), | ||
147 | }; | ||
148 | |||
149 | static struct clk_div_table div_hclk_cpu_t[] = { | ||
150 | { .val = 0, .div = 1 }, | ||
151 | { .val = 1, .div = 2 }, | ||
152 | { .val = 3, .div = 4 }, | ||
153 | { /* sentinel */}, | ||
154 | }; | ||
155 | |||
156 | #define MFLAGS CLK_MUX_HIWORD_MASK | ||
157 | #define DFLAGS CLK_DIVIDER_HIWORD_MASK | ||
158 | #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) | ||
159 | |||
160 | static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { | ||
161 | /* | ||
162 | * Clock-Architecture Diagram 1 | ||
163 | */ | ||
164 | |||
165 | GATE(0, "apll_core", "apll", 0, | ||
166 | RK3288_CLKGATE_CON(0), 1, GFLAGS), | ||
167 | GATE(0, "gpll_core", "gpll", 0, | ||
168 | RK3288_CLKGATE_CON(0), 2, GFLAGS), | ||
169 | COMPOSITE_NOGATE(0, "armclk", mux_armclk_p, 0, | ||
170 | RK3288_CLKSEL_CON(0), 15, 1, MFLAGS, 8, 5, DFLAGS), | ||
171 | |||
172 | COMPOSITE_NOMUX(0, "armcore0", "armclk", 0, | ||
173 | RK3288_CLKSEL_CON(36), 0, 3, DFLAGS, | ||
174 | RK3288_CLKGATE_CON(12), 0, GFLAGS), | ||
175 | COMPOSITE_NOMUX(0, "armcore1", "armclk", 0, | ||
176 | RK3288_CLKSEL_CON(36), 4, 3, DFLAGS, | ||
177 | RK3288_CLKGATE_CON(12), 1, GFLAGS), | ||
178 | COMPOSITE_NOMUX(0, "armcore2", "armclk", 0, | ||
179 | RK3288_CLKSEL_CON(36), 8, 3, DFLAGS, | ||
180 | RK3288_CLKGATE_CON(12), 2, GFLAGS), | ||
181 | COMPOSITE_NOMUX(0, "armcore3", "armclk", 0, | ||
182 | RK3288_CLKSEL_CON(36), 12, 3, DFLAGS, | ||
183 | RK3288_CLKGATE_CON(12), 3, GFLAGS), | ||
184 | COMPOSITE_NOMUX(0, "l2ram", "armclk", 0, | ||
185 | RK3288_CLKSEL_CON(37), 0, 3, DFLAGS, | ||
186 | RK3288_CLKGATE_CON(12), 4, GFLAGS), | ||
187 | COMPOSITE_NOMUX(0, "aclk_core_m0", "armclk", 0, | ||
188 | RK3288_CLKSEL_CON(0), 0, 4, DFLAGS, | ||
189 | RK3288_CLKGATE_CON(12), 5, GFLAGS), | ||
190 | COMPOSITE_NOMUX(0, "aclk_core_mp", "armclk", 0, | ||
191 | RK3288_CLKSEL_CON(0), 4, 4, DFLAGS, | ||
192 | RK3288_CLKGATE_CON(12), 6, GFLAGS), | ||
193 | COMPOSITE_NOMUX(0, "atclk", "armclk", 0, | ||
194 | RK3288_CLKSEL_CON(37), 4, 5, DFLAGS, | ||
195 | RK3288_CLKGATE_CON(12), 7, GFLAGS), | ||
196 | COMPOSITE_NOMUX(0, "pclk_dbg_pre", "armclk", 0, | ||
197 | RK3288_CLKSEL_CON(37), 9, 5, DFLAGS, | ||
198 | RK3288_CLKGATE_CON(12), 8, GFLAGS), | ||
199 | GATE(0, "pclk_dbg", "pclk_dbg_pre", 0, | ||
200 | RK3288_CLKGATE_CON(12), 9, GFLAGS), | ||
201 | GATE(0, "cs_dbg", "pclk_dbg_pre", 0, | ||
202 | RK3288_CLKGATE_CON(12), 10, GFLAGS), | ||
203 | GATE(0, "pclk_core_niu", "pclk_dbg_pre", 0, | ||
204 | RK3288_CLKGATE_CON(12), 11, GFLAGS), | ||
205 | |||
206 | GATE(0, "dpll_ddr", "dpll", 0, | ||
207 | RK3288_CLKGATE_CON(0), 8, GFLAGS), | ||
208 | GATE(0, "gpll_ddr", "gpll", 0, | ||
209 | RK3288_CLKGATE_CON(0), 9, GFLAGS), | ||
210 | COMPOSITE_NOGATE(0, "ddrphy", mux_ddrphy_p, 0, | ||
211 | RK3288_CLKSEL_CON(26), 2, 1, MFLAGS, 0, 2, | ||
212 | DFLAGS | CLK_DIVIDER_POWER_OF_TWO), | ||
213 | |||
214 | GATE(0, "gpll_aclk_cpu", "gpll", 0, | ||
215 | RK3288_CLKGATE_CON(0), 10, GFLAGS), | ||
216 | GATE(0, "cpll_aclk_cpu", "cpll", 0, | ||
217 | RK3288_CLKGATE_CON(0), 11, GFLAGS), | ||
218 | COMPOSITE_NOGATE(0, "aclk_cpu_src", mux_aclk_cpu_src_p, 0, | ||
219 | RK3288_CLKSEL_CON(1), 15, 1, MFLAGS, 3, 5, DFLAGS), | ||
220 | DIV(0, "aclk_cpu_pre", "aclk_cpu_src", 0, | ||
221 | RK3288_CLKSEL_CON(1), 0, 3, DFLAGS), | ||
222 | GATE(0, "aclk_cpu", "aclk_cpu_pre", 0, | ||
223 | RK3288_CLKGATE_CON(0), 3, GFLAGS), | ||
224 | COMPOSITE_NOMUX(0, "pclk_cpu", "aclk_cpu_pre", 0, | ||
225 | RK3288_CLKSEL_CON(1), 12, 3, DFLAGS, | ||
226 | RK3288_CLKGATE_CON(0), 5, GFLAGS), | ||
227 | COMPOSITE_NOMUX_DIVTBL(0, "hclk_cpu", "aclk_cpu_pre", 0, | ||
228 | RK3288_CLKSEL_CON(1), 8, 2, DFLAGS, div_hclk_cpu_t, | ||
229 | RK3288_CLKGATE_CON(0), 4, GFLAGS), | ||
230 | GATE(0, "c2c_host", "aclk_cpu_src", 0, | ||
231 | RK3288_CLKGATE_CON(13), 8, GFLAGS), | ||
232 | COMPOSITE_NOMUX(0, "crypto", "aclk_cpu_pre", 0, | ||
233 | RK3288_CLKSEL_CON(26), 6, 2, DFLAGS, | ||
234 | RK3288_CLKGATE_CON(5), 4, GFLAGS), | ||
235 | GATE(0, "aclk_bus_2pmu", "aclk_cpu_pre", 0, | ||
236 | RK3288_CLKGATE_CON(0), 7, GFLAGS), | ||
237 | |||
238 | COMPOSITE(0, "i2s_src", mux_pll_src_cpll_gpll_p, 0, | ||
239 | RK3288_CLKSEL_CON(4), 15, 1, MFLAGS, 0, 7, DFLAGS, | ||
240 | RK3288_CLKGATE_CON(4), 1, GFLAGS), | ||
241 | COMPOSITE_FRAC(0, "i2s_frac", "i2s_src", 0, | ||
242 | RK3288_CLKSEL_CON(8), 0, | ||
243 | RK3288_CLKGATE_CON(4), 2, GFLAGS), | ||
244 | MUX(0, "i2s_pre", mux_i2s_pre_p, 0, | ||
245 | RK3288_CLKSEL_CON(4), 8, 2, MFLAGS), | ||
246 | COMPOSITE_NODIV(0, "i2s0_clkout", mux_i2s_clkout_p, 0, | ||
247 | RK3288_CLKSEL_CON(4), 12, 1, MFLAGS, | ||
248 | RK3288_CLKGATE_CON(4), 0, GFLAGS), | ||
249 | GATE(SCLK_I2S0, "sclk_i2s0", "i2s_pre", 0, | ||
250 | RK3288_CLKGATE_CON(4), 3, GFLAGS), | ||
251 | |||
252 | MUX(0, "spdif_src", mux_pll_src_cpll_gpll_p, 0, | ||
253 | RK3288_CLKSEL_CON(5), 15, 1, MFLAGS), | ||
254 | COMPOSITE_NOMUX(0, "spdif_pre", "spdif_src", 0, | ||
255 | RK3288_CLKSEL_CON(5), 0, 7, DFLAGS, | ||
256 | RK3288_CLKGATE_CON(4), 4, GFLAGS), | ||
257 | COMPOSITE_FRAC(0, "spdif_frac", "spdif_src", 0, | ||
258 | RK3288_CLKSEL_CON(9), 0, | ||
259 | RK3288_CLKGATE_CON(4), 5, GFLAGS), | ||
260 | COMPOSITE_NODIV(SCLK_SPDIF, "sclk_spdif", mux_spdif_p, 0, | ||
261 | RK3288_CLKSEL_CON(5), 8, 2, MFLAGS, | ||
262 | RK3288_CLKGATE_CON(4), 6, GFLAGS), | ||
263 | COMPOSITE_NOMUX(0, "spdif_8ch_pre", "spdif_src", 0, | ||
264 | RK3288_CLKSEL_CON(40), 0, 7, DFLAGS, | ||
265 | RK3288_CLKGATE_CON(4), 7, GFLAGS), | ||
266 | COMPOSITE_FRAC(0, "spdif_8ch_frac", "spdif_8ch_src", 0, | ||
267 | RK3288_CLKSEL_CON(41), 0, | ||
268 | RK3288_CLKGATE_CON(4), 8, GFLAGS), | ||
269 | COMPOSITE_NODIV(SCLK_SPDIF8CH, "sclk_spdif_8ch", mux_spdif_8ch_p, 0, | ||
270 | RK3288_CLKSEL_CON(40), 8, 2, MFLAGS, | ||
271 | RK3288_CLKGATE_CON(4), 9, GFLAGS), | ||
272 | |||
273 | GATE(0, "sclk_acc_efuse", "xin24m", 0, | ||
274 | RK3288_CLKGATE_CON(0), 12, GFLAGS), | ||
275 | |||
276 | GATE(SCLK_TIMER0, "sclk_timer0", "xin24m", 0, | ||
277 | RK3288_CLKGATE_CON(1), 0, GFLAGS), | ||
278 | GATE(SCLK_TIMER1, "sclk_timer1", "xin24m", 0, | ||
279 | RK3288_CLKGATE_CON(1), 1, GFLAGS), | ||
280 | GATE(SCLK_TIMER2, "sclk_timer2", "xin24m", 0, | ||
281 | RK3288_CLKGATE_CON(1), 2, GFLAGS), | ||
282 | GATE(SCLK_TIMER3, "sclk_timer3", "xin24m", 0, | ||
283 | RK3288_CLKGATE_CON(1), 3, GFLAGS), | ||
284 | GATE(SCLK_TIMER4, "sclk_timer4", "xin24m", 0, | ||
285 | RK3288_CLKGATE_CON(1), 4, GFLAGS), | ||
286 | GATE(SCLK_TIMER5, "sclk_timer5", "xin24m", 0, | ||
287 | RK3288_CLKGATE_CON(1), 5, GFLAGS), | ||
288 | |||
289 | /* | ||
290 | * Clock-Architecture Diagram 2 | ||
291 | */ | ||
292 | |||
293 | COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
294 | RK3288_CLKSEL_CON(32), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
295 | RK3288_CLKGATE_CON(3), 9, GFLAGS), | ||
296 | COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
297 | RK3288_CLKSEL_CON(32), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
298 | RK3288_CLKGATE_CON(3), 11, GFLAGS), | ||
299 | |||
300 | COMPOSITE(0, "aclk_vio0", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
301 | RK3288_CLKSEL_CON(31), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
302 | RK3288_CLKGATE_CON(3), 0, GFLAGS), | ||
303 | DIV(0, "hclk_vio", "aclk_vio0", 0, | ||
304 | RK3288_CLKSEL_CON(28), 8, 5, DFLAGS), | ||
305 | COMPOSITE(0, "aclk_vio1", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
306 | RK3288_CLKSEL_CON(31), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
307 | RK3288_CLKGATE_CON(3), 2, GFLAGS), | ||
308 | |||
309 | COMPOSITE(0, "aclk_rga_pre", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
310 | RK3288_CLKSEL_CON(30), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
311 | RK3288_CLKGATE_CON(3), 5, GFLAGS), | ||
312 | COMPOSITE(0, "sclk_rga", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
313 | RK3288_CLKSEL_CON(30), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
314 | RK3288_CLKGATE_CON(3), 4, GFLAGS), | ||
315 | |||
316 | COMPOSITE(DCLK_VOP0, "dclk_vop0", mux_pll_src_cpll_gpll_npll_p, 0, | ||
317 | RK3288_CLKSEL_CON(27), 0, 2, MFLAGS, 8, 8, DFLAGS, | ||
318 | RK3288_CLKGATE_CON(3), 1, GFLAGS), | ||
319 | COMPOSITE(DCLK_VOP1, "dclk_vop1", mux_pll_src_cpll_gpll_npll_p, 0, | ||
320 | RK3288_CLKSEL_CON(29), 6, 2, MFLAGS, 8, 8, DFLAGS, | ||
321 | RK3288_CLKGATE_CON(3), 3, GFLAGS), | ||
322 | |||
323 | COMPOSITE_NODIV(0, "sclk_edp_24m", mux_edp_24m_p, 0, | ||
324 | RK3288_CLKSEL_CON(28), 15, 1, MFLAGS, | ||
325 | RK3288_CLKGATE_CON(3), 12, GFLAGS), | ||
326 | COMPOSITE(0, "sclk_edp", mux_pll_src_cpll_gpll_npll_p, 0, | ||
327 | RK3288_CLKSEL_CON(28), 6, 2, MFLAGS, 0, 6, DFLAGS, | ||
328 | RK3288_CLKGATE_CON(3), 13, GFLAGS), | ||
329 | |||
330 | COMPOSITE(0, "sclk_isp", mux_pll_src_cpll_gpll_npll_p, 0, | ||
331 | RK3288_CLKSEL_CON(6), 6, 2, MFLAGS, 0, 6, DFLAGS, | ||
332 | RK3288_CLKGATE_CON(3), 14, GFLAGS), | ||
333 | COMPOSITE(0, "sclk_isp_jpe", mux_pll_src_cpll_gpll_npll_p, 0, | ||
334 | RK3288_CLKSEL_CON(6), 14, 2, MFLAGS, 8, 6, DFLAGS, | ||
335 | RK3288_CLKGATE_CON(3), 15, GFLAGS), | ||
336 | |||
337 | GATE(0, "sclk_hdmi_hdcp", "xin24m", 0, | ||
338 | RK3288_CLKGATE_CON(5), 12, GFLAGS), | ||
339 | GATE(0, "sclk_hdmi_cec", "xin32k", 0, | ||
340 | RK3288_CLKGATE_CON(5), 11, GFLAGS), | ||
341 | |||
342 | COMPOSITE(0, "aclk_hevc", mux_pll_src_cpll_gpll_npll_p, 0, | ||
343 | RK3288_CLKSEL_CON(39), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
344 | RK3288_CLKGATE_CON(13), 13, GFLAGS), | ||
345 | DIV(0, "hclk_hevc", "aclk_hevc", 0, | ||
346 | RK3288_CLKSEL_CON(40), 12, 2, DFLAGS), | ||
347 | |||
348 | COMPOSITE(0, "sclk_hevc_cabac", mux_pll_src_cpll_gpll_npll_p, 0, | ||
349 | RK3288_CLKSEL_CON(42), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
350 | RK3288_CLKGATE_CON(13), 14, GFLAGS), | ||
351 | COMPOSITE(0, "sclk_hevc_core", mux_pll_src_cpll_gpll_npll_p, 0, | ||
352 | RK3288_CLKSEL_CON(42), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
353 | RK3288_CLKGATE_CON(13), 15, GFLAGS), | ||
354 | |||
355 | COMPOSITE_NODIV(0, "vip_src", mux_pll_src_cpll_gpll_p, 0, | ||
356 | RK3288_CLKSEL_CON(26), 8, 1, MFLAGS, | ||
357 | RK3288_CLKGATE_CON(3), 7, GFLAGS), | ||
358 | COMPOSITE_NOGATE(0, "sclk_vip_out", mux_cif_out_p, 0, | ||
359 | RK3288_CLKSEL_CON(26), 15, 1, MFLAGS, 9, 5, DFLAGS), | ||
360 | |||
361 | DIV(0, "pclk_pd_alive", "gpll", 0, | ||
362 | RK3288_CLKSEL_CON(33), 8, 5, DFLAGS), | ||
363 | COMPOSITE_NOMUX(0, "pclk_pd_pmu", "gpll", 0, | ||
364 | RK3288_CLKSEL_CON(33), 0, 5, DFLAGS, | ||
365 | RK3288_CLKGATE_CON(5), 8, GFLAGS), | ||
366 | |||
367 | COMPOSITE(SCLK_GPU, "sclk_gpu", mux_pll_src_cpll_gpll_usb480m_p, 0, | ||
368 | RK3288_CLKSEL_CON(34), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
369 | RK3288_CLKGATE_CON(5), 7, GFLAGS), | ||
370 | |||
371 | COMPOSITE(0, "aclk_peri_src", mux_pll_src_cpll_gpll_p, 0, | ||
372 | RK3288_CLKSEL_CON(10), 15, 1, MFLAGS, 0, 5, DFLAGS, | ||
373 | RK3288_CLKGATE_CON(2), 0, GFLAGS), | ||
374 | COMPOSITE_NOMUX(0, "pclk_peri", "aclk_peri_src", 0, | ||
375 | RK3288_CLKSEL_CON(10), 12, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
376 | RK3288_CLKGATE_CON(2), 3, GFLAGS), | ||
377 | COMPOSITE_NOMUX(0, "hclk_peri", "aclk_peri_src", 0, | ||
378 | RK3288_CLKSEL_CON(10), 8, 2, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, | ||
379 | RK3288_CLKGATE_CON(2), 2, GFLAGS), | ||
380 | GATE(0, "aclk_peri", "aclk_peri_src", 0, | ||
381 | RK3288_CLKGATE_CON(2), 1, GFLAGS), | ||
382 | |||
383 | /* | ||
384 | * Clock-Architecture Diagram 3 | ||
385 | */ | ||
386 | |||
387 | COMPOSITE(SCLK_SPI0, "sclk_spi0", mux_pll_src_cpll_gpll_p, 0, | ||
388 | RK3288_CLKSEL_CON(25), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
389 | RK3288_CLKGATE_CON(2), 9, GFLAGS), | ||
390 | COMPOSITE(SCLK_SPI1, "sclk_spi1", mux_pll_src_cpll_gpll_p, 0, | ||
391 | RK3288_CLKSEL_CON(25), 15, 1, MFLAGS, 8, 7, DFLAGS, | ||
392 | RK3288_CLKGATE_CON(2), 10, GFLAGS), | ||
393 | COMPOSITE(SCLK_SPI2, "sclk_spi2", mux_pll_src_cpll_gpll_p, 0, | ||
394 | RK3288_CLKSEL_CON(39), 7, 1, MFLAGS, 0, 7, DFLAGS, | ||
395 | RK3288_CLKGATE_CON(2), 11, GFLAGS), | ||
396 | |||
397 | COMPOSITE(SCLK_SDMMC, "sclk_sdmmc", mux_mmc_src_p, 0, | ||
398 | RK3288_CLKSEL_CON(11), 6, 2, MFLAGS, 0, 6, DFLAGS, | ||
399 | RK3288_CLKGATE_CON(13), 0, GFLAGS), | ||
400 | COMPOSITE(SCLK_SDIO0, "sclk_sdio0", mux_mmc_src_p, 0, | ||
401 | RK3288_CLKSEL_CON(12), 6, 2, MFLAGS, 0, 6, DFLAGS, | ||
402 | RK3288_CLKGATE_CON(13), 1, GFLAGS), | ||
403 | COMPOSITE(SCLK_SDIO1, "sclk_sdio1", mux_mmc_src_p, 0, | ||
404 | RK3288_CLKSEL_CON(34), 14, 2, MFLAGS, 8, 6, DFLAGS, | ||
405 | RK3288_CLKGATE_CON(13), 2, GFLAGS), | ||
406 | COMPOSITE(SCLK_EMMC, "sclk_emmc", mux_mmc_src_p, 0, | ||
407 | RK3288_CLKSEL_CON(12), 14, 2, MFLAGS, 8, 6, DFLAGS, | ||
408 | RK3288_CLKGATE_CON(13), 3, GFLAGS), | ||
409 | |||
410 | COMPOSITE(0, "sclk_tspout", mux_tspout_p, 0, | ||
411 | RK3288_CLKSEL_CON(35), 14, 2, MFLAGS, 8, 5, DFLAGS, | ||
412 | RK3288_CLKGATE_CON(4), 11, GFLAGS), | ||
413 | COMPOSITE(0, "sclk_tsp", mux_pll_src_cpll_gpll_npll_p, 0, | ||
414 | RK3288_CLKSEL_CON(35), 6, 2, MFLAGS, 0, 5, DFLAGS, | ||
415 | RK3288_CLKGATE_CON(4), 10, GFLAGS), | ||
416 | |||
417 | GATE(SCLK_OTGPHY0, "sclk_otgphy0", "usb480m", 0, | ||
418 | RK3288_CLKGATE_CON(13), 4, GFLAGS), | ||
419 | GATE(SCLK_OTGPHY1, "sclk_otgphy1", "usb480m", 0, | ||
420 | RK3288_CLKGATE_CON(13), 5, GFLAGS), | ||
421 | GATE(SCLK_OTGPHY2, "sclk_otgphy2", "usb480m", 0, | ||
422 | RK3288_CLKGATE_CON(13), 6, GFLAGS), | ||
423 | GATE(SCLK_OTG_ADP, "sclk_otg_adp", "xin32k", 0, | ||
424 | RK3288_CLKGATE_CON(13), 7, GFLAGS), | ||
425 | |||
426 | COMPOSITE_NOMUX(SCLK_TSADC, "sclk_tsadc", "xin32k", 0, | ||
427 | RK3288_CLKSEL_CON(2), 0, 6, DFLAGS, | ||
428 | RK3288_CLKGATE_CON(2), 7, GFLAGS), | ||
429 | |||
430 | COMPOSITE_NOMUX(SCLK_SARADC, "sclk_saradc", "xin24m", 0, | ||
431 | RK3288_CLKSEL_CON(24), 8, 8, DFLAGS, | ||
432 | RK3288_CLKGATE_CON(2), 8, GFLAGS), | ||
433 | |||
434 | GATE(SCLK_PS2C, "sclk_ps2c", "xin24m", 0, | ||
435 | RK3288_CLKGATE_CON(5), 13, GFLAGS), | ||
436 | |||
437 | COMPOSITE(SCLK_NANDC0, "sclk_nandc0", mux_pll_src_cpll_gpll_p, 0, | ||
438 | RK3288_CLKSEL_CON(38), 7, 1, MFLAGS, 0, 5, DFLAGS, | ||
439 | RK3288_CLKGATE_CON(5), 5, GFLAGS), | ||
440 | COMPOSITE(SCLK_NANDC1, "sclk_nandc1", mux_pll_src_cpll_gpll_p, 0, | ||
441 | RK3288_CLKSEL_CON(38), 15, 1, MFLAGS, 8, 5, DFLAGS, | ||
442 | RK3288_CLKGATE_CON(5), 6, GFLAGS), | ||
443 | |||
444 | COMPOSITE(0, "uart0_src", mux_uart0_pll_p, 0, | ||
445 | RK3288_CLKSEL_CON(13), 13, 2, MFLAGS, 0, 7, DFLAGS, | ||
446 | RK3288_CLKGATE_CON(1), 8, GFLAGS), | ||
447 | COMPOSITE_FRAC(0, "uart0_frac", "uart0_src", 0, | ||
448 | RK3288_CLKSEL_CON(17), 0, | ||
449 | RK3288_CLKGATE_CON(1), 9, GFLAGS), | ||
450 | MUX(SCLK_UART0, "sclk_uart0", mux_uart0_p, 0, | ||
451 | RK3288_CLKSEL_CON(13), 8, 2, MFLAGS), | ||
452 | MUX(0, "uart_src", mux_pll_src_cpll_gpll_p, 0, | ||
453 | RK3288_CLKSEL_CON(13), 15, 1, MFLAGS), | ||
454 | COMPOSITE_NOMUX(0, "uart1_src", "uart_src", 0, | ||
455 | RK3288_CLKSEL_CON(14), 0, 7, DFLAGS, | ||
456 | RK3288_CLKGATE_CON(1), 10, GFLAGS), | ||
457 | COMPOSITE_FRAC(0, "uart1_frac", "uart1_src", 0, | ||
458 | RK3288_CLKSEL_CON(18), 0, | ||
459 | RK3288_CLKGATE_CON(1), 11, GFLAGS), | ||
460 | MUX(SCLK_UART1, "sclk_uart1", mux_uart1_p, 0, | ||
461 | RK3288_CLKSEL_CON(14), 8, 2, MFLAGS), | ||
462 | COMPOSITE_NOMUX(0, "uart2_src", "uart_src", 0, | ||
463 | RK3288_CLKSEL_CON(15), 0, 7, DFLAGS, | ||
464 | RK3288_CLKGATE_CON(1), 12, GFLAGS), | ||
465 | COMPOSITE_FRAC(0, "uart2_frac", "uart2_src", 0, | ||
466 | RK3288_CLKSEL_CON(19), 0, | ||
467 | RK3288_CLKGATE_CON(1), 13, GFLAGS), | ||
468 | MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, 0, | ||
469 | RK3288_CLKSEL_CON(15), 8, 2, MFLAGS), | ||
470 | COMPOSITE_NOMUX(0, "uart3_src", "uart_src", 0, | ||
471 | RK3288_CLKSEL_CON(16), 0, 7, DFLAGS, | ||
472 | RK3288_CLKGATE_CON(1), 14, GFLAGS), | ||
473 | COMPOSITE_FRAC(0, "uart3_frac", "uart3_src", 0, | ||
474 | RK3288_CLKSEL_CON(20), 0, | ||
475 | RK3288_CLKGATE_CON(1), 15, GFLAGS), | ||
476 | MUX(SCLK_UART3, "sclk_uart3", mux_uart3_p, 0, | ||
477 | RK3288_CLKSEL_CON(16), 8, 2, MFLAGS), | ||
478 | COMPOSITE_NOMUX(0, "uart4_src", "uart_src", 0, | ||
479 | RK3288_CLKSEL_CON(3), 0, 7, DFLAGS, | ||
480 | RK3288_CLKGATE_CON(2), 12, GFLAGS), | ||
481 | COMPOSITE_FRAC(0, "uart4_frac", "uart4_src", 0, | ||
482 | RK3288_CLKSEL_CON(7), 0, | ||
483 | RK3288_CLKGATE_CON(2), 13, GFLAGS), | ||
484 | MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, 0, | ||
485 | RK3288_CLKSEL_CON(3), 8, 2, MFLAGS), | ||
486 | |||
487 | COMPOSITE(0, "mac_src", mux_pll_src_npll_cpll_gpll_p, 0, | ||
488 | RK3288_CLKSEL_CON(21), 0, 2, MFLAGS, 8, 5, DFLAGS, | ||
489 | RK3288_CLKGATE_CON(2), 5, GFLAGS), | ||
490 | MUX(0, "macref", mux_macref_p, 0, | ||
491 | RK3288_CLKSEL_CON(21), 4, 1, MFLAGS), | ||
492 | GATE(0, "sclk_macref_out", "macref", 0, | ||
493 | RK3288_CLKGATE_CON(5), 3, GFLAGS), | ||
494 | GATE(SCLK_MACREF, "sclk_macref", "macref", 0, | ||
495 | RK3288_CLKGATE_CON(5), 2, GFLAGS), | ||
496 | GATE(SCLK_MAC_RX, "sclk_mac_rx", "macref", 0, | ||
497 | RK3288_CLKGATE_CON(5), 0, GFLAGS), | ||
498 | GATE(SCLK_MAC_TX, "sclk_mac_tx", "macref", 0, | ||
499 | RK3288_CLKGATE_CON(5), 1, GFLAGS), | ||
500 | |||
501 | COMPOSITE(0, "hsadc_src", mux_pll_src_cpll_gpll_p, 0, | ||
502 | RK3288_CLKSEL_CON(22), 0, 1, MFLAGS, 8, 8, DFLAGS, | ||
503 | RK3288_CLKGATE_CON(2), 6, GFLAGS), | ||
504 | MUX(SCLK_HSADC, "sclk_hsadc_out", mux_hsadcout_p, 0, | ||
505 | RK3288_CLKSEL_CON(22), 4, 1, MFLAGS), | ||
506 | |||
507 | GATE(0, "jtag", "ext_jtag", 0, | ||
508 | RK3288_CLKGATE_CON(4), 14, GFLAGS), | ||
509 | |||
510 | COMPOSITE_NODIV(0, "usbphy480m_src", mux_usbphy480m_p, 0, | ||
511 | RK3288_CLKSEL_CON(13), 11, 2, MFLAGS, | ||
512 | RK3288_CLKGATE_CON(5), 15, GFLAGS), | ||
513 | COMPOSITE_NODIV(SCLK_HSICPHY480M, "sclk_hsicphy480m", mux_hsicphy480m_p, 0, | ||
514 | RK3288_CLKSEL_CON(29), 0, 2, MFLAGS, | ||
515 | RK3288_CLKGATE_CON(3), 6, GFLAGS), | ||
516 | GATE(0, "hsicphy12m_xin12m", "xin12m", 0, | ||
517 | RK3288_CLKGATE_CON(13), 9, GFLAGS), | ||
518 | DIV(0, "hsicphy12m_usbphy", "sclk_hsicphy480m", 0, | ||
519 | RK3288_CLKSEL_CON(11), 8, 6, DFLAGS), | ||
520 | MUX(SCLK_HSICPHY12M, "sclk_hsicphy12m", mux_hsicphy12m_p, 0, | ||
521 | RK3288_CLKSEL_CON(22), 4, 1, MFLAGS), | ||
522 | |||
523 | /* | ||
524 | * Clock-Architecture Diagram 4 | ||
525 | */ | ||
526 | |||
527 | /* aclk_cpu gates */ | ||
528 | GATE(0, "sclk_intmem0", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 5, GFLAGS), | ||
529 | GATE(0, "sclk_intmem1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 6, GFLAGS), | ||
530 | GATE(0, "sclk_intmem2", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 7, GFLAGS), | ||
531 | GATE(ACLK_DMAC1, "aclk_dmac1", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 12, GFLAGS), | ||
532 | GATE(0, "aclk_strc_sys", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 13, GFLAGS), | ||
533 | GATE(0, "aclk_intmem", "aclk_cpu", 0, RK3288_CLKGATE_CON(10), 4, GFLAGS), | ||
534 | GATE(ACLK_CRYPTO, "aclk_crypto", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 6, GFLAGS), | ||
535 | GATE(0, "aclk_ccp", "aclk_cpu", 0, RK3288_CLKGATE_CON(11), 8, GFLAGS), | ||
536 | |||
537 | /* hclk_cpu gates */ | ||
538 | GATE(HCLK_CRYPTO, "hclk_crypto", "hclk_cpu", 0, RK3288_CLKGATE_CON(11), 7, GFLAGS), | ||
539 | GATE(HCLK_I2S0, "hclk_i2s0", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 8, GFLAGS), | ||
540 | GATE(HCLK_ROM, "hclk_rom", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 9, GFLAGS), | ||
541 | GATE(HCLK_SPDIF, "hclk_spdif", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 10, GFLAGS), | ||
542 | GATE(HCLK_SPDIF8CH, "hclk_spdif_8ch", "hclk_cpu", 0, RK3288_CLKGATE_CON(10), 11, GFLAGS), | ||
543 | |||
544 | /* pclk_cpu gates */ | ||
545 | GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS), | ||
546 | GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS), | ||
547 | GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS), | ||
548 | GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), | ||
549 | GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS), | ||
550 | GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), | ||
551 | GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), | ||
552 | GATE(0, "pclk_publ1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 1, GFLAGS), | ||
553 | GATE(0, "pclk_efuse_1024", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 2, GFLAGS), | ||
554 | GATE(PCLK_TZPC, "pclk_tzpc", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 3, GFLAGS), | ||
555 | GATE(PCLK_UART2, "pclk_uart2", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 9, GFLAGS), | ||
556 | GATE(0, "pclk_efuse_256", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 10, GFLAGS), | ||
557 | GATE(PCLK_RKPWM, "pclk_rkpwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 11, GFLAGS), | ||
558 | |||
559 | /* ddrctrl [DDR Controller PHY clock] gates */ | ||
560 | GATE(0, "nclk_ddrupctl0", "ddrphy", 0, RK3288_CLKGATE_CON(11), 4, GFLAGS), | ||
561 | GATE(0, "nclk_ddrupctl1", "ddrphy", 0, RK3288_CLKGATE_CON(11), 5, GFLAGS), | ||
562 | |||
563 | /* ddrphy gates */ | ||
564 | GATE(0, "sclk_ddrphy0", "ddrphy", 0, RK3288_CLKGATE_CON(4), 12, GFLAGS), | ||
565 | GATE(0, "sclk_ddrphy1", "ddrphy", 0, RK3288_CLKGATE_CON(4), 13, GFLAGS), | ||
566 | |||
567 | /* aclk_peri gates */ | ||
568 | GATE(0, "aclk_peri_axi_matrix", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 2, GFLAGS), | ||
569 | GATE(ACLK_DMAC2, "aclk_dmac2", "aclk_peri", 0, RK3288_CLKGATE_CON(6), 3, GFLAGS), | ||
570 | GATE(0, "aclk_peri_niu", "aclk_peri", 0, RK3288_CLKGATE_CON(7), 11, GFLAGS), | ||
571 | GATE(ACLK_MMU, "aclk_mmu", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 12, GFLAGS), | ||
572 | GATE(ACLK_GMAC, "aclk_gmac", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 0, GFLAGS), | ||
573 | GATE(HCLK_GPS, "hclk_gps", "aclk_peri", 0, RK3288_CLKGATE_CON(8), 2, GFLAGS), | ||
574 | |||
575 | /* hclk_peri gates */ | ||
576 | GATE(0, "hclk_peri_matrix", "hclk_peri", 0, RK3288_CLKGATE_CON(6), 0, GFLAGS), | ||
577 | GATE(HCLK_OTG0, "hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 4, GFLAGS), | ||
578 | GATE(HCLK_USBHOST0, "hclk_host0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 6, GFLAGS), | ||
579 | GATE(HCLK_USBHOST1, "hclk_host1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 7, GFLAGS), | ||
580 | GATE(HCLK_HSIC, "hclk_hsic", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 8, GFLAGS), | ||
581 | GATE(0, "hclk_usb_peri", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 9, GFLAGS), | ||
582 | GATE(0, "hclk_peri_ahb_arbi", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 10, GFLAGS), | ||
583 | GATE(0, "hclk_emem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 12, GFLAGS), | ||
584 | GATE(0, "hclk_mem", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 13, GFLAGS), | ||
585 | GATE(HCLK_NANDC0, "hclk_nandc0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 14, GFLAGS), | ||
586 | GATE(HCLK_NANDC1, "hclk_nandc1", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 15, GFLAGS), | ||
587 | GATE(HCLK_TSP, "hclk_tsp", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 8, GFLAGS), | ||
588 | GATE(HCLK_SDMMC, "hclk_sdmmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 3, GFLAGS), | ||
589 | GATE(HCLK_SDIO0, "hclk_sdio0", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 4, GFLAGS), | ||
590 | GATE(HCLK_SDIO1, "hclk_sdio1", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 5, GFLAGS), | ||
591 | GATE(HCLK_EMMC, "hclk_emmc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 6, GFLAGS), | ||
592 | GATE(HCLK_HSADC, "hclk_hsadc", "hclk_peri", 0, RK3288_CLKGATE_CON(8), 7, GFLAGS), | ||
593 | GATE(0, "pmu_hclk_otg0", "hclk_peri", 0, RK3288_CLKGATE_CON(7), 5, GFLAGS), | ||
594 | |||
595 | /* pclk_peri gates */ | ||
596 | GATE(0, "pclk_peri_matrix", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 1, GFLAGS), | ||
597 | GATE(PCLK_SPI0, "pclk_spi0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 4, GFLAGS), | ||
598 | GATE(PCLK_SPI1, "pclk_spi1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 5, GFLAGS), | ||
599 | GATE(PCLK_SPI2, "pclk_spi2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 6, GFLAGS), | ||
600 | GATE(PCLK_PS2C, "pclk_ps2c", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 7, GFLAGS), | ||
601 | GATE(PCLK_UART0, "pclk_uart0", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 8, GFLAGS), | ||
602 | GATE(PCLK_UART1, "pclk_uart1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 9, GFLAGS), | ||
603 | GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS), | ||
604 | GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS), | ||
605 | GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS), | ||
606 | GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS), | ||
607 | GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS), | ||
608 | GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS), | ||
609 | GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS), | ||
610 | GATE(PCLK_SIM, "pclk_sim", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 3, GFLAGS), | ||
611 | GATE(PCLK_I2C5, "pclk_i2c5", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 0, GFLAGS), | ||
612 | GATE(PCLK_GMAC, "pclk_gmac", "pclk_peri", 0, RK3288_CLKGATE_CON(8), 1, GFLAGS), | ||
613 | |||
614 | GATE(SCLK_LCDC_PWM0, "sclk_lcdc_pwm0", "xin24m", 0, RK3288_CLKGATE_CON(13), 10, GFLAGS), | ||
615 | GATE(SCLK_LCDC_PWM1, "sclk_lcdc_pwm1", "xin24m", 0, RK3288_CLKGATE_CON(13), 11, GFLAGS), | ||
616 | GATE(0, "sclk_pvtm_core", "xin24m", 0, RK3288_CLKGATE_CON(5), 9, GFLAGS), | ||
617 | GATE(0, "sclk_pvtm_gpu", "xin24m", 0, RK3288_CLKGATE_CON(5), 10, GFLAGS), | ||
618 | GATE(0, "sclk_mipidsi_24m", "xin24m", 0, RK3288_CLKGATE_CON(5), 15, GFLAGS), | ||
619 | |||
620 | /* sclk_gpu gates */ | ||
621 | GATE(ACLK_GPU, "aclk_gpu", "sclk_gpu", 0, RK3288_CLKGATE_CON(18), 0, GFLAGS), | ||
622 | |||
623 | /* pclk_pd_alive gates */ | ||
624 | GATE(PCLK_GPIO8, "pclk_gpio8", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 8, GFLAGS), | ||
625 | GATE(PCLK_GPIO7, "pclk_gpio7", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 7, GFLAGS), | ||
626 | GATE(PCLK_GPIO1, "pclk_gpio1", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 1, GFLAGS), | ||
627 | GATE(PCLK_GPIO2, "pclk_gpio2", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 2, GFLAGS), | ||
628 | GATE(PCLK_GPIO3, "pclk_gpio3", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 3, GFLAGS), | ||
629 | GATE(PCLK_GPIO4, "pclk_gpio4", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 4, GFLAGS), | ||
630 | GATE(PCLK_GPIO5, "pclk_gpio5", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 5, GFLAGS), | ||
631 | GATE(PCLK_GPIO6, "pclk_gpio6", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 6, GFLAGS), | ||
632 | GATE(PCLK_GRF, "pclk_grf", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 11, GFLAGS), | ||
633 | GATE(0, "pclk_alive_niu", "pclk_pd_alive", 0, RK3288_CLKGATE_CON(14), 12, GFLAGS), | ||
634 | |||
635 | /* pclk_pd_pmu gates */ | ||
636 | GATE(PCLK_PMU, "pclk_pmu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 0, GFLAGS), | ||
637 | GATE(0, "pclk_intmem1", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 1, GFLAGS), | ||
638 | GATE(0, "pclk_pmu_niu", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 2, GFLAGS), | ||
639 | GATE(PCLK_SGRF, "pclk_sgrf", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 3, GFLAGS), | ||
640 | GATE(PCLK_GPIO0, "pclk_gpio0", "pclk_pd_pmu", 0, RK3288_CLKGATE_CON(17), 4, GFLAGS), | ||
641 | |||
642 | /* hclk_vio gates */ | ||
643 | GATE(HCLK_RGA, "hclk_rga", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 1, GFLAGS), | ||
644 | GATE(HCLK_VOP0, "hclk_vop0", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 6, GFLAGS), | ||
645 | GATE(HCLK_VOP1, "hclk_vop1", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 8, GFLAGS), | ||
646 | GATE(0, "hclk_vio_ahb_arbi", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 9, GFLAGS), | ||
647 | GATE(0, "hclk_vio_niu", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 10, GFLAGS), | ||
648 | GATE(0, "hclk_vip", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 15, GFLAGS), | ||
649 | GATE(HCLK_IEP, "hclk_iep", "hclk_vio", 0, RK3288_CLKGATE_CON(15), 3, GFLAGS), | ||
650 | GATE(HCLK_ISP, "hclk_isp", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 1, GFLAGS), | ||
651 | GATE(0, "hclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 10, GFLAGS), | ||
652 | GATE(0, "pclk_mipi_dsi0", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 4, GFLAGS), | ||
653 | GATE(0, "pclk_mipi_dsi1", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 5, GFLAGS), | ||
654 | GATE(0, "pclk_mipi_csi", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 6, GFLAGS), | ||
655 | GATE(0, "pclk_lvds_phy", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 7, GFLAGS), | ||
656 | GATE(0, "pclk_edp_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 8, GFLAGS), | ||
657 | GATE(0, "pclk_hdmi_ctrl", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 9, GFLAGS), | ||
658 | GATE(0, "pclk_vio2_h2p", "hclk_vio", 0, RK3288_CLKGATE_CON(16), 11, GFLAGS), | ||
659 | |||
660 | /* aclk_vio0 gates */ | ||
661 | GATE(ACLK_VOP0, "aclk_vop0", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 5, GFLAGS), | ||
662 | GATE(0, "aclk_iep", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 2, GFLAGS), | ||
663 | GATE(0, "aclk_vio0_niu", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 11, GFLAGS), | ||
664 | GATE(0, "aclk_vip", "aclk_vio0", 0, RK3288_CLKGATE_CON(15), 14, GFLAGS), | ||
665 | |||
666 | /* aclk_vio1 gates */ | ||
667 | GATE(ACLK_VOP1, "aclk_vop1", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 7, GFLAGS), | ||
668 | GATE(0, "aclk_isp", "aclk_vio1", 0, RK3288_CLKGATE_CON(16), 2, GFLAGS), | ||
669 | GATE(0, "aclk_vio1_niu", "aclk_vio1", 0, RK3288_CLKGATE_CON(15), 12, GFLAGS), | ||
670 | |||
671 | /* aclk_rga_pre gates */ | ||
672 | GATE(ACLK_RGA, "aclk_rga", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 0, GFLAGS), | ||
673 | GATE(0, "aclk_rga_niu", "aclk_rga_pre", 0, RK3288_CLKGATE_CON(15), 13, GFLAGS), | ||
674 | |||
675 | /* | ||
676 | * Other ungrouped clocks. | ||
677 | */ | ||
678 | |||
679 | GATE(0, "pclk_vip_in", "ext_vip", 0, RK3288_CLKGATE_CON(16), 0, GFLAGS), | ||
680 | GATE(0, "pclk_isp_in", "ext_isp", 0, RK3288_CLKGATE_CON(16), 3, GFLAGS), | ||
681 | }; | ||
682 | |||
683 | static void __init rk3288_clk_init(struct device_node *np) | ||
684 | { | ||
685 | void __iomem *reg_base; | ||
686 | struct clk *clk; | ||
687 | |||
688 | reg_base = of_iomap(np, 0); | ||
689 | if (!reg_base) { | ||
690 | pr_err("%s: could not map cru region\n", __func__); | ||
691 | return; | ||
692 | } | ||
693 | |||
694 | rockchip_clk_init(np, reg_base, CLK_NR_CLKS); | ||
695 | |||
696 | /* xin12m is created by an cru-internal divider */ | ||
697 | clk = clk_register_fixed_factor(NULL, "xin12m", "xin24m", 0, 1, 2); | ||
698 | if (IS_ERR(clk)) | ||
699 | pr_warn("%s: could not register clock xin12m: %ld\n", | ||
700 | __func__, PTR_ERR(clk)); | ||
701 | |||
702 | |||
703 | clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); | ||
704 | if (IS_ERR(clk)) | ||
705 | pr_warn("%s: could not register clock usb480m: %ld\n", | ||
706 | __func__, PTR_ERR(clk)); | ||
707 | |||
708 | rockchip_clk_register_plls(rk3288_pll_clks, | ||
709 | ARRAY_SIZE(rk3288_pll_clks), | ||
710 | RK3288_GRF_SOC_STATUS); | ||
711 | rockchip_clk_register_branches(rk3288_clk_branches, | ||
712 | ARRAY_SIZE(rk3288_clk_branches)); | ||
713 | |||
714 | rockchip_register_softrst(np, 9, reg_base + RK3288_SOFTRST_CON(0), | ||
715 | ROCKCHIP_SOFTRST_HIWORD_MASK); | ||
716 | } | ||
717 | CLK_OF_DECLARE(rk3288_cru, "rockchip,rk3288-cru", rk3288_clk_init); | ||
diff --git a/drivers/clk/rockchip/clk.c b/drivers/clk/rockchip/clk.c new file mode 100644 index 000000000000..278cf9dd1e23 --- /dev/null +++ b/drivers/clk/rockchip/clk.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
4 | * | ||
5 | * based on | ||
6 | * | ||
7 | * samsung/clk.c | ||
8 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
9 | * Copyright (c) 2013 Linaro Ltd. | ||
10 | * Author: Thomas Abraham <thomas.ab@samsung.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | */ | ||
22 | |||
23 | #include <linux/slab.h> | ||
24 | #include <linux/clk.h> | ||
25 | #include <linux/clk-provider.h> | ||
26 | #include <linux/mfd/syscon.h> | ||
27 | #include <linux/regmap.h> | ||
28 | #include "clk.h" | ||
29 | |||
30 | /** | ||
31 | * Register a clock branch. | ||
32 | * Most clock branches have a form like | ||
33 | * | ||
34 | * src1 --|--\ | ||
35 | * |M |--[GATE]-[DIV]- | ||
36 | * src2 --|--/ | ||
37 | * | ||
38 | * sometimes without one of those components. | ||
39 | */ | ||
40 | struct clk *rockchip_clk_register_branch(const char *name, | ||
41 | const char **parent_names, u8 num_parents, void __iomem *base, | ||
42 | int muxdiv_offset, u8 mux_shift, u8 mux_width, u8 mux_flags, | ||
43 | u8 div_shift, u8 div_width, u8 div_flags, | ||
44 | struct clk_div_table *div_table, int gate_offset, | ||
45 | u8 gate_shift, u8 gate_flags, unsigned long flags, | ||
46 | spinlock_t *lock) | ||
47 | { | ||
48 | struct clk *clk; | ||
49 | struct clk_mux *mux = NULL; | ||
50 | struct clk_gate *gate = NULL; | ||
51 | struct clk_divider *div = NULL; | ||
52 | const struct clk_ops *mux_ops = NULL, *div_ops = NULL, | ||
53 | *gate_ops = NULL; | ||
54 | |||
55 | if (num_parents > 1) { | ||
56 | mux = kzalloc(sizeof(*mux), GFP_KERNEL); | ||
57 | if (!mux) | ||
58 | return ERR_PTR(-ENOMEM); | ||
59 | |||
60 | mux->reg = base + muxdiv_offset; | ||
61 | mux->shift = mux_shift; | ||
62 | mux->mask = BIT(mux_width) - 1; | ||
63 | mux->flags = mux_flags; | ||
64 | mux->lock = lock; | ||
65 | mux_ops = (mux_flags & CLK_MUX_READ_ONLY) ? &clk_mux_ro_ops | ||
66 | : &clk_mux_ops; | ||
67 | } | ||
68 | |||
69 | if (gate_offset >= 0) { | ||
70 | gate = kzalloc(sizeof(*gate), GFP_KERNEL); | ||
71 | if (!gate) | ||
72 | return ERR_PTR(-ENOMEM); | ||
73 | |||
74 | gate->flags = gate_flags; | ||
75 | gate->reg = base + gate_offset; | ||
76 | gate->bit_idx = gate_shift; | ||
77 | gate->lock = lock; | ||
78 | gate_ops = &clk_gate_ops; | ||
79 | } | ||
80 | |||
81 | if (div_width > 0) { | ||
82 | div = kzalloc(sizeof(*div), GFP_KERNEL); | ||
83 | if (!div) | ||
84 | return ERR_PTR(-ENOMEM); | ||
85 | |||
86 | div->flags = div_flags; | ||
87 | div->reg = base + muxdiv_offset; | ||
88 | div->shift = div_shift; | ||
89 | div->width = div_width; | ||
90 | div->lock = lock; | ||
91 | div->table = div_table; | ||
92 | div_ops = (div_flags & CLK_DIVIDER_READ_ONLY) | ||
93 | ? &clk_divider_ro_ops | ||
94 | : &clk_divider_ops; | ||
95 | } | ||
96 | |||
97 | clk = clk_register_composite(NULL, name, parent_names, num_parents, | ||
98 | mux ? &mux->hw : NULL, mux_ops, | ||
99 | div ? &div->hw : NULL, div_ops, | ||
100 | gate ? &gate->hw : NULL, gate_ops, | ||
101 | flags); | ||
102 | |||
103 | return clk; | ||
104 | } | ||
105 | |||
106 | static DEFINE_SPINLOCK(clk_lock); | ||
107 | static struct clk **clk_table; | ||
108 | static void __iomem *reg_base; | ||
109 | static struct clk_onecell_data clk_data; | ||
110 | static struct device_node *cru_node; | ||
111 | static struct regmap *grf; | ||
112 | |||
113 | void __init rockchip_clk_init(struct device_node *np, void __iomem *base, | ||
114 | unsigned long nr_clks) | ||
115 | { | ||
116 | reg_base = base; | ||
117 | cru_node = np; | ||
118 | grf = ERR_PTR(-EPROBE_DEFER); | ||
119 | |||
120 | clk_table = kcalloc(nr_clks, sizeof(struct clk *), GFP_KERNEL); | ||
121 | if (!clk_table) | ||
122 | pr_err("%s: could not allocate clock lookup table\n", __func__); | ||
123 | |||
124 | clk_data.clks = clk_table; | ||
125 | clk_data.clk_num = nr_clks; | ||
126 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
127 | } | ||
128 | |||
129 | struct regmap *rockchip_clk_get_grf(void) | ||
130 | { | ||
131 | if (IS_ERR(grf)) | ||
132 | grf = syscon_regmap_lookup_by_phandle(cru_node, "rockchip,grf"); | ||
133 | return grf; | ||
134 | } | ||
135 | |||
136 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id) | ||
137 | { | ||
138 | if (clk_table && id) | ||
139 | clk_table[id] = clk; | ||
140 | } | ||
141 | |||
142 | void __init rockchip_clk_register_plls(struct rockchip_pll_clock *list, | ||
143 | unsigned int nr_pll, int grf_lock_offset) | ||
144 | { | ||
145 | struct clk *clk; | ||
146 | int idx; | ||
147 | |||
148 | for (idx = 0; idx < nr_pll; idx++, list++) { | ||
149 | clk = rockchip_clk_register_pll(list->type, list->name, | ||
150 | list->parent_names, list->num_parents, | ||
151 | reg_base, list->con_offset, grf_lock_offset, | ||
152 | list->lock_shift, list->mode_offset, | ||
153 | list->mode_shift, list->rate_table, &clk_lock); | ||
154 | if (IS_ERR(clk)) { | ||
155 | pr_err("%s: failed to register clock %s\n", __func__, | ||
156 | list->name); | ||
157 | continue; | ||
158 | } | ||
159 | |||
160 | rockchip_clk_add_lookup(clk, list->id); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | void __init rockchip_clk_register_branches( | ||
165 | struct rockchip_clk_branch *list, | ||
166 | unsigned int nr_clk) | ||
167 | { | ||
168 | struct clk *clk = NULL; | ||
169 | unsigned int idx; | ||
170 | unsigned long flags; | ||
171 | |||
172 | for (idx = 0; idx < nr_clk; idx++, list++) { | ||
173 | flags = list->flags; | ||
174 | |||
175 | /* catch simple muxes */ | ||
176 | switch (list->branch_type) { | ||
177 | case branch_mux: | ||
178 | clk = clk_register_mux(NULL, list->name, | ||
179 | list->parent_names, list->num_parents, | ||
180 | flags, reg_base + list->muxdiv_offset, | ||
181 | list->mux_shift, list->mux_width, | ||
182 | list->mux_flags, &clk_lock); | ||
183 | break; | ||
184 | case branch_divider: | ||
185 | if (list->div_table) | ||
186 | clk = clk_register_divider_table(NULL, | ||
187 | list->name, list->parent_names[0], | ||
188 | flags, reg_base + list->muxdiv_offset, | ||
189 | list->div_shift, list->div_width, | ||
190 | list->div_flags, list->div_table, | ||
191 | &clk_lock); | ||
192 | else | ||
193 | clk = clk_register_divider(NULL, list->name, | ||
194 | list->parent_names[0], flags, | ||
195 | reg_base + list->muxdiv_offset, | ||
196 | list->div_shift, list->div_width, | ||
197 | list->div_flags, &clk_lock); | ||
198 | break; | ||
199 | case branch_fraction_divider: | ||
200 | /* unimplemented */ | ||
201 | continue; | ||
202 | break; | ||
203 | case branch_gate: | ||
204 | flags |= CLK_SET_RATE_PARENT; | ||
205 | |||
206 | /* keep all gates untouched for now */ | ||
207 | flags |= CLK_IGNORE_UNUSED; | ||
208 | |||
209 | clk = clk_register_gate(NULL, list->name, | ||
210 | list->parent_names[0], flags, | ||
211 | reg_base + list->gate_offset, | ||
212 | list->gate_shift, list->gate_flags, &clk_lock); | ||
213 | break; | ||
214 | case branch_composite: | ||
215 | /* keep all gates untouched for now */ | ||
216 | flags |= CLK_IGNORE_UNUSED; | ||
217 | |||
218 | clk = rockchip_clk_register_branch(list->name, | ||
219 | list->parent_names, list->num_parents, | ||
220 | reg_base, list->muxdiv_offset, list->mux_shift, | ||
221 | list->mux_width, list->mux_flags, | ||
222 | list->div_shift, list->div_width, | ||
223 | list->div_flags, list->div_table, | ||
224 | list->gate_offset, list->gate_shift, | ||
225 | list->gate_flags, flags, &clk_lock); | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | /* none of the cases above matched */ | ||
230 | if (!clk) { | ||
231 | pr_err("%s: unknown clock type %d\n", | ||
232 | __func__, list->branch_type); | ||
233 | continue; | ||
234 | } | ||
235 | |||
236 | if (IS_ERR(clk)) { | ||
237 | pr_err("%s: failed to register clock %s: %ld\n", | ||
238 | __func__, list->name, PTR_ERR(clk)); | ||
239 | continue; | ||
240 | } | ||
241 | |||
242 | rockchip_clk_add_lookup(clk, list->id); | ||
243 | } | ||
244 | } | ||
diff --git a/drivers/clk/rockchip/clk.h b/drivers/clk/rockchip/clk.h new file mode 100644 index 000000000000..887cbdeca2aa --- /dev/null +++ b/drivers/clk/rockchip/clk.h | |||
@@ -0,0 +1,347 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
4 | * | ||
5 | * based on | ||
6 | * | ||
7 | * samsung/clk.h | ||
8 | * Copyright (c) 2013 Samsung Electronics Co., Ltd. | ||
9 | * Copyright (c) 2013 Linaro Ltd. | ||
10 | * Author: Thomas Abraham <thomas.ab@samsung.com> | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify | ||
13 | * it under the terms of the GNU General Public License as published by | ||
14 | * the Free Software Foundation; either version 2 of the License, or | ||
15 | * (at your option) any later version. | ||
16 | * | ||
17 | * This program is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | */ | ||
22 | |||
23 | #ifndef CLK_ROCKCHIP_CLK_H | ||
24 | #define CLK_ROCKCHIP_CLK_H | ||
25 | |||
26 | #include <linux/io.h> | ||
27 | #include <linux/clk.h> | ||
28 | #include <linux/clk-provider.h> | ||
29 | |||
30 | #define HIWORD_UPDATE(val, mask, shift) \ | ||
31 | ((val) << (shift) | (mask) << ((shift) + 16)) | ||
32 | |||
33 | /* register positions shared by RK2928, RK3066 and RK3188 */ | ||
34 | #define RK2928_PLL_CON(x) (x * 0x4) | ||
35 | #define RK2928_MODE_CON 0x40 | ||
36 | #define RK2928_CLKSEL_CON(x) (x * 0x4 + 0x44) | ||
37 | #define RK2928_CLKGATE_CON(x) (x * 0x4 + 0xd0) | ||
38 | #define RK2928_GLB_SRST_FST 0x100 | ||
39 | #define RK2928_GLB_SRST_SND 0x104 | ||
40 | #define RK2928_SOFTRST_CON(x) (x * 0x4 + 0x110) | ||
41 | #define RK2928_MISC_CON 0x134 | ||
42 | |||
43 | #define RK3288_PLL_CON(x) RK2928_PLL_CON(x) | ||
44 | #define RK3288_MODE_CON 0x50 | ||
45 | #define RK3288_CLKSEL_CON(x) (x * 0x4 + 0x60) | ||
46 | #define RK3288_CLKGATE_CON(x) (x * 0x4 + 0x160) | ||
47 | #define RK3288_GLB_SRST_FST 0x1b0 | ||
48 | #define RK3288_GLB_SRST_SND 0x1b4 | ||
49 | #define RK3288_SOFTRST_CON(x) (x * 0x4 + 0x1b8) | ||
50 | #define RK3288_MISC_CON 0x1e8 | ||
51 | |||
52 | enum rockchip_pll_type { | ||
53 | pll_rk3066, | ||
54 | }; | ||
55 | |||
56 | #define RK3066_PLL_RATE(_rate, _nr, _nf, _no) \ | ||
57 | { \ | ||
58 | .rate = _rate##U, \ | ||
59 | .nr = _nr, \ | ||
60 | .nf = _nf, \ | ||
61 | .no = _no, \ | ||
62 | .bwadj = (_nf >> 1), \ | ||
63 | } | ||
64 | |||
65 | struct rockchip_pll_rate_table { | ||
66 | unsigned long rate; | ||
67 | unsigned int nr; | ||
68 | unsigned int nf; | ||
69 | unsigned int no; | ||
70 | unsigned int bwadj; | ||
71 | }; | ||
72 | |||
73 | /** | ||
74 | * struct rockchip_pll_clock: information about pll clock | ||
75 | * @id: platform specific id of the clock. | ||
76 | * @name: name of this pll clock. | ||
77 | * @parent_name: name of the parent clock. | ||
78 | * @flags: optional flags for basic clock. | ||
79 | * @con_offset: offset of the register for configuring the PLL. | ||
80 | * @mode_offset: offset of the register for configuring the PLL-mode. | ||
81 | * @mode_shift: offset inside the mode-register for the mode of this pll. | ||
82 | * @lock_shift: offset inside the lock register for the lock status. | ||
83 | * @type: Type of PLL to be registered. | ||
84 | * @rate_table: Table of usable pll rates | ||
85 | */ | ||
86 | struct rockchip_pll_clock { | ||
87 | unsigned int id; | ||
88 | const char *name; | ||
89 | const char **parent_names; | ||
90 | u8 num_parents; | ||
91 | unsigned long flags; | ||
92 | int con_offset; | ||
93 | int mode_offset; | ||
94 | int mode_shift; | ||
95 | int lock_shift; | ||
96 | enum rockchip_pll_type type; | ||
97 | struct rockchip_pll_rate_table *rate_table; | ||
98 | }; | ||
99 | |||
100 | #define PLL(_type, _id, _name, _pnames, _flags, _con, _mode, _mshift, \ | ||
101 | _lshift, _rtable) \ | ||
102 | { \ | ||
103 | .id = _id, \ | ||
104 | .type = _type, \ | ||
105 | .name = _name, \ | ||
106 | .parent_names = _pnames, \ | ||
107 | .num_parents = ARRAY_SIZE(_pnames), \ | ||
108 | .flags = CLK_GET_RATE_NOCACHE | _flags, \ | ||
109 | .con_offset = _con, \ | ||
110 | .mode_offset = _mode, \ | ||
111 | .mode_shift = _mshift, \ | ||
112 | .lock_shift = _lshift, \ | ||
113 | .rate_table = _rtable, \ | ||
114 | } | ||
115 | |||
116 | struct clk *rockchip_clk_register_pll(enum rockchip_pll_type pll_type, | ||
117 | const char *name, const char **parent_names, u8 num_parents, | ||
118 | void __iomem *base, int con_offset, int grf_lock_offset, | ||
119 | int lock_shift, int reg_mode, int mode_shift, | ||
120 | struct rockchip_pll_rate_table *rate_table, | ||
121 | spinlock_t *lock); | ||
122 | |||
123 | #define PNAME(x) static const char *x[] __initconst | ||
124 | |||
125 | enum rockchip_clk_branch_type { | ||
126 | branch_composite, | ||
127 | branch_mux, | ||
128 | branch_divider, | ||
129 | branch_fraction_divider, | ||
130 | branch_gate, | ||
131 | }; | ||
132 | |||
133 | struct rockchip_clk_branch { | ||
134 | unsigned int id; | ||
135 | enum rockchip_clk_branch_type branch_type; | ||
136 | const char *name; | ||
137 | const char **parent_names; | ||
138 | u8 num_parents; | ||
139 | unsigned long flags; | ||
140 | int muxdiv_offset; | ||
141 | u8 mux_shift; | ||
142 | u8 mux_width; | ||
143 | u8 mux_flags; | ||
144 | u8 div_shift; | ||
145 | u8 div_width; | ||
146 | u8 div_flags; | ||
147 | struct clk_div_table *div_table; | ||
148 | int gate_offset; | ||
149 | u8 gate_shift; | ||
150 | u8 gate_flags; | ||
151 | }; | ||
152 | |||
153 | #define COMPOSITE(_id, cname, pnames, f, mo, ms, mw, mf, ds, dw,\ | ||
154 | df, go, gs, gf) \ | ||
155 | { \ | ||
156 | .id = _id, \ | ||
157 | .branch_type = branch_composite, \ | ||
158 | .name = cname, \ | ||
159 | .parent_names = pnames, \ | ||
160 | .num_parents = ARRAY_SIZE(pnames), \ | ||
161 | .flags = f, \ | ||
162 | .muxdiv_offset = mo, \ | ||
163 | .mux_shift = ms, \ | ||
164 | .mux_width = mw, \ | ||
165 | .mux_flags = mf, \ | ||
166 | .div_shift = ds, \ | ||
167 | .div_width = dw, \ | ||
168 | .div_flags = df, \ | ||
169 | .gate_offset = go, \ | ||
170 | .gate_shift = gs, \ | ||
171 | .gate_flags = gf, \ | ||
172 | } | ||
173 | |||
174 | #define COMPOSITE_NOMUX(_id, cname, pname, f, mo, ds, dw, df, \ | ||
175 | go, gs, gf) \ | ||
176 | { \ | ||
177 | .id = _id, \ | ||
178 | .branch_type = branch_composite, \ | ||
179 | .name = cname, \ | ||
180 | .parent_names = (const char *[]){ pname }, \ | ||
181 | .num_parents = 1, \ | ||
182 | .flags = f, \ | ||
183 | .muxdiv_offset = mo, \ | ||
184 | .div_shift = ds, \ | ||
185 | .div_width = dw, \ | ||
186 | .div_flags = df, \ | ||
187 | .gate_offset = go, \ | ||
188 | .gate_shift = gs, \ | ||
189 | .gate_flags = gf, \ | ||
190 | } | ||
191 | |||
192 | #define COMPOSITE_NOMUX_DIVTBL(_id, cname, pname, f, mo, ds, dw,\ | ||
193 | df, dt, go, gs, gf) \ | ||
194 | { \ | ||
195 | .id = _id, \ | ||
196 | .branch_type = branch_composite, \ | ||
197 | .name = cname, \ | ||
198 | .parent_names = (const char *[]){ pname }, \ | ||
199 | .num_parents = 1, \ | ||
200 | .flags = f, \ | ||
201 | .muxdiv_offset = mo, \ | ||
202 | .div_shift = ds, \ | ||
203 | .div_width = dw, \ | ||
204 | .div_flags = df, \ | ||
205 | .div_table = dt, \ | ||
206 | .gate_offset = go, \ | ||
207 | .gate_shift = gs, \ | ||
208 | .gate_flags = gf, \ | ||
209 | } | ||
210 | |||
211 | #define COMPOSITE_NODIV(_id, cname, pnames, f, mo, ms, mw, mf, \ | ||
212 | go, gs, gf) \ | ||
213 | { \ | ||
214 | .id = _id, \ | ||
215 | .branch_type = branch_composite, \ | ||
216 | .name = cname, \ | ||
217 | .parent_names = pnames, \ | ||
218 | .num_parents = ARRAY_SIZE(pnames), \ | ||
219 | .flags = f, \ | ||
220 | .muxdiv_offset = mo, \ | ||
221 | .mux_shift = ms, \ | ||
222 | .mux_width = mw, \ | ||
223 | .mux_flags = mf, \ | ||
224 | .gate_offset = go, \ | ||
225 | .gate_shift = gs, \ | ||
226 | .gate_flags = gf, \ | ||
227 | } | ||
228 | |||
229 | #define COMPOSITE_NOGATE(_id, cname, pnames, f, mo, ms, mw, mf, \ | ||
230 | ds, dw, df) \ | ||
231 | { \ | ||
232 | .id = _id, \ | ||
233 | .branch_type = branch_composite, \ | ||
234 | .name = cname, \ | ||
235 | .parent_names = pnames, \ | ||
236 | .num_parents = ARRAY_SIZE(pnames), \ | ||
237 | .flags = f, \ | ||
238 | .muxdiv_offset = mo, \ | ||
239 | .mux_shift = ms, \ | ||
240 | .mux_width = mw, \ | ||
241 | .mux_flags = mf, \ | ||
242 | .div_shift = ds, \ | ||
243 | .div_width = dw, \ | ||
244 | .div_flags = df, \ | ||
245 | .gate_offset = -1, \ | ||
246 | } | ||
247 | |||
248 | #define COMPOSITE_FRAC(_id, cname, pname, f, mo, df, go, gs, gf)\ | ||
249 | { \ | ||
250 | .id = _id, \ | ||
251 | .branch_type = branch_fraction_divider, \ | ||
252 | .name = cname, \ | ||
253 | .parent_names = (const char *[]){ pname }, \ | ||
254 | .num_parents = 1, \ | ||
255 | .flags = f, \ | ||
256 | .muxdiv_offset = mo, \ | ||
257 | .div_shift = 16, \ | ||
258 | .div_width = 16, \ | ||
259 | .div_flags = df, \ | ||
260 | .gate_offset = go, \ | ||
261 | .gate_shift = gs, \ | ||
262 | .gate_flags = gf, \ | ||
263 | } | ||
264 | |||
265 | #define MUX(_id, cname, pnames, f, o, s, w, mf) \ | ||
266 | { \ | ||
267 | .id = _id, \ | ||
268 | .branch_type = branch_mux, \ | ||
269 | .name = cname, \ | ||
270 | .parent_names = pnames, \ | ||
271 | .num_parents = ARRAY_SIZE(pnames), \ | ||
272 | .flags = f, \ | ||
273 | .muxdiv_offset = o, \ | ||
274 | .mux_shift = s, \ | ||
275 | .mux_width = w, \ | ||
276 | .mux_flags = mf, \ | ||
277 | .gate_offset = -1, \ | ||
278 | } | ||
279 | |||
280 | #define DIV(_id, cname, pname, f, o, s, w, df) \ | ||
281 | { \ | ||
282 | .id = _id, \ | ||
283 | .branch_type = branch_divider, \ | ||
284 | .name = cname, \ | ||
285 | .parent_names = (const char *[]){ pname }, \ | ||
286 | .num_parents = 1, \ | ||
287 | .flags = f, \ | ||
288 | .muxdiv_offset = o, \ | ||
289 | .div_shift = s, \ | ||
290 | .div_width = w, \ | ||
291 | .div_flags = df, \ | ||
292 | .gate_offset = -1, \ | ||
293 | } | ||
294 | |||
295 | #define DIVTBL(_id, cname, pname, f, o, s, w, df, dt) \ | ||
296 | { \ | ||
297 | .id = _id, \ | ||
298 | .branch_type = branch_divider, \ | ||
299 | .name = cname, \ | ||
300 | .parent_names = (const char *[]){ pname }, \ | ||
301 | .num_parents = 1, \ | ||
302 | .flags = f, \ | ||
303 | .muxdiv_offset = o, \ | ||
304 | .div_shift = s, \ | ||
305 | .div_width = w, \ | ||
306 | .div_flags = df, \ | ||
307 | .div_table = dt, \ | ||
308 | } | ||
309 | |||
310 | #define GATE(_id, cname, pname, f, o, b, gf) \ | ||
311 | { \ | ||
312 | .id = _id, \ | ||
313 | .branch_type = branch_gate, \ | ||
314 | .name = cname, \ | ||
315 | .parent_names = (const char *[]){ pname }, \ | ||
316 | .num_parents = 1, \ | ||
317 | .flags = f, \ | ||
318 | .gate_offset = o, \ | ||
319 | .gate_shift = b, \ | ||
320 | .gate_flags = gf, \ | ||
321 | } | ||
322 | |||
323 | |||
324 | void rockchip_clk_init(struct device_node *np, void __iomem *base, | ||
325 | unsigned long nr_clks); | ||
326 | struct regmap *rockchip_clk_get_grf(void); | ||
327 | void rockchip_clk_add_lookup(struct clk *clk, unsigned int id); | ||
328 | void rockchip_clk_register_branches(struct rockchip_clk_branch *clk_list, | ||
329 | unsigned int nr_clk); | ||
330 | void rockchip_clk_register_plls(struct rockchip_pll_clock *pll_list, | ||
331 | unsigned int nr_pll, int grf_lock_offset); | ||
332 | |||
333 | #define ROCKCHIP_SOFTRST_HIWORD_MASK BIT(0) | ||
334 | |||
335 | #ifdef CONFIG_RESET_CONTROLLER | ||
336 | void rockchip_register_softrst(struct device_node *np, | ||
337 | unsigned int num_regs, | ||
338 | void __iomem *base, u8 flags); | ||
339 | #else | ||
340 | static inline void rockchip_register_softrst(struct device_node *np, | ||
341 | unsigned int num_regs, | ||
342 | void __iomem *base, u8 flags) | ||
343 | { | ||
344 | } | ||
345 | #endif | ||
346 | |||
347 | #endif | ||
diff --git a/drivers/clk/rockchip/softrst.c b/drivers/clk/rockchip/softrst.c new file mode 100644 index 000000000000..552f7bb15bc5 --- /dev/null +++ b/drivers/clk/rockchip/softrst.c | |||
@@ -0,0 +1,118 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 MundoReader S.L. | ||
3 | * Author: Heiko Stuebner <heiko@sntech.de> | ||
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 as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or | ||
8 | * (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/slab.h> | ||
17 | #include <linux/io.h> | ||
18 | #include <linux/reset-controller.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | #include "clk.h" | ||
21 | |||
22 | struct rockchip_softrst { | ||
23 | struct reset_controller_dev rcdev; | ||
24 | void __iomem *reg_base; | ||
25 | int num_regs; | ||
26 | int num_per_reg; | ||
27 | u8 flags; | ||
28 | spinlock_t lock; | ||
29 | }; | ||
30 | |||
31 | static int rockchip_softrst_assert(struct reset_controller_dev *rcdev, | ||
32 | unsigned long id) | ||
33 | { | ||
34 | struct rockchip_softrst *softrst = container_of(rcdev, | ||
35 | struct rockchip_softrst, | ||
36 | rcdev); | ||
37 | int bank = id / softrst->num_per_reg; | ||
38 | int offset = id % softrst->num_per_reg; | ||
39 | |||
40 | if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { | ||
41 | writel(BIT(offset) | (BIT(offset) << 16), | ||
42 | softrst->reg_base + (bank * 4)); | ||
43 | } else { | ||
44 | unsigned long flags; | ||
45 | u32 reg; | ||
46 | |||
47 | spin_lock_irqsave(&softrst->lock, flags); | ||
48 | |||
49 | reg = readl(softrst->reg_base + (bank * 4)); | ||
50 | writel(reg | BIT(offset), softrst->reg_base + (bank * 4)); | ||
51 | |||
52 | spin_unlock_irqrestore(&softrst->lock, flags); | ||
53 | } | ||
54 | |||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | static int rockchip_softrst_deassert(struct reset_controller_dev *rcdev, | ||
59 | unsigned long id) | ||
60 | { | ||
61 | struct rockchip_softrst *softrst = container_of(rcdev, | ||
62 | struct rockchip_softrst, | ||
63 | rcdev); | ||
64 | int bank = id / softrst->num_per_reg; | ||
65 | int offset = id % softrst->num_per_reg; | ||
66 | |||
67 | if (softrst->flags & ROCKCHIP_SOFTRST_HIWORD_MASK) { | ||
68 | writel((BIT(offset) << 16), softrst->reg_base + (bank * 4)); | ||
69 | } else { | ||
70 | unsigned long flags; | ||
71 | u32 reg; | ||
72 | |||
73 | spin_lock_irqsave(&softrst->lock, flags); | ||
74 | |||
75 | reg = readl(softrst->reg_base + (bank * 4)); | ||
76 | writel(reg & ~BIT(offset), softrst->reg_base + (bank * 4)); | ||
77 | |||
78 | spin_unlock_irqrestore(&softrst->lock, flags); | ||
79 | } | ||
80 | |||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static struct reset_control_ops rockchip_softrst_ops = { | ||
85 | .assert = rockchip_softrst_assert, | ||
86 | .deassert = rockchip_softrst_deassert, | ||
87 | }; | ||
88 | |||
89 | void __init rockchip_register_softrst(struct device_node *np, | ||
90 | unsigned int num_regs, | ||
91 | void __iomem *base, u8 flags) | ||
92 | { | ||
93 | struct rockchip_softrst *softrst; | ||
94 | int ret; | ||
95 | |||
96 | softrst = kzalloc(sizeof(*softrst), GFP_KERNEL); | ||
97 | if (!softrst) | ||
98 | return; | ||
99 | |||
100 | spin_lock_init(&softrst->lock); | ||
101 | |||
102 | softrst->reg_base = base; | ||
103 | softrst->flags = flags; | ||
104 | softrst->num_regs = num_regs; | ||
105 | softrst->num_per_reg = (flags & ROCKCHIP_SOFTRST_HIWORD_MASK) ? 16 | ||
106 | : 32; | ||
107 | |||
108 | softrst->rcdev.owner = THIS_MODULE; | ||
109 | softrst->rcdev.nr_resets = num_regs * softrst->num_per_reg; | ||
110 | softrst->rcdev.ops = &rockchip_softrst_ops; | ||
111 | softrst->rcdev.of_node = np; | ||
112 | ret = reset_controller_register(&softrst->rcdev); | ||
113 | if (ret) { | ||
114 | pr_err("%s: could not register reset controller, %d\n", | ||
115 | __func__, ret); | ||
116 | kfree(softrst); | ||
117 | } | ||
118 | }; | ||