Commit | Line | Data |
---|---|---|
5a465808 JN |
1 | /* |
2 | * Copyright 2014 Linaro Ltd. | |
3 | * Copyright (C) 2014 ZTE Corporation. | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify | |
6 | * it under the terms of the GNU General Public License version 2 as | |
7 | * published by the Free Software Foundation. | |
8 | */ | |
9 | ||
10 | #include <linux/clk-provider.h> | |
11 | #include <linux/of_address.h> | |
12 | #include <dt-bindings/clock/zx296702-clock.h> | |
13 | #include "clk.h" | |
14 | ||
15 | static DEFINE_SPINLOCK(reg_lock); | |
16 | ||
17 | static void __iomem *topcrm_base; | |
18 | static void __iomem *lsp0crpm_base; | |
19 | static void __iomem *lsp1crpm_base; | |
20 | ||
21 | static struct clk *topclk[ZX296702_TOPCLK_END]; | |
22 | static struct clk *lsp0clk[ZX296702_LSP0CLK_END]; | |
23 | static struct clk *lsp1clk[ZX296702_LSP1CLK_END]; | |
24 | ||
25 | static struct clk_onecell_data topclk_data; | |
26 | static struct clk_onecell_data lsp0clk_data; | |
27 | static struct clk_onecell_data lsp1clk_data; | |
28 | ||
29 | #define CLK_MUX (topcrm_base + 0x04) | |
30 | #define CLK_DIV (topcrm_base + 0x08) | |
31 | #define CLK_EN0 (topcrm_base + 0x0c) | |
32 | #define CLK_EN1 (topcrm_base + 0x10) | |
33 | #define VOU_LOCAL_CLKEN (topcrm_base + 0x68) | |
34 | #define VOU_LOCAL_CLKSEL (topcrm_base + 0x70) | |
35 | #define VOU_LOCAL_DIV2_SET (topcrm_base + 0x74) | |
36 | #define CLK_MUX1 (topcrm_base + 0x8c) | |
37 | ||
38 | #define CLK_SDMMC1 (lsp0crpm_base + 0x0c) | |
105644e5 JN |
39 | #define CLK_GPIO (lsp0crpm_base + 0x2c) |
40 | #define CLK_SPDIF0 (lsp0crpm_base + 0x10) | |
41 | #define SPDIF0_DIV (lsp0crpm_base + 0x14) | |
42 | #define CLK_I2S0 (lsp0crpm_base + 0x18) | |
43 | #define I2S0_DIV (lsp0crpm_base + 0x1c) | |
44 | #define CLK_I2S1 (lsp0crpm_base + 0x20) | |
45 | #define I2S1_DIV (lsp0crpm_base + 0x24) | |
46 | #define CLK_I2S2 (lsp0crpm_base + 0x34) | |
47 | #define I2S2_DIV (lsp0crpm_base + 0x38) | |
5a465808 JN |
48 | |
49 | #define CLK_UART0 (lsp1crpm_base + 0x20) | |
50 | #define CLK_UART1 (lsp1crpm_base + 0x24) | |
51 | #define CLK_SDMMC0 (lsp1crpm_base + 0x2c) | |
105644e5 JN |
52 | #define CLK_SPDIF1 (lsp1crpm_base + 0x30) |
53 | #define SPDIF1_DIV (lsp1crpm_base + 0x34) | |
5a465808 JN |
54 | |
55 | static const struct zx_pll_config pll_a9_config[] = { | |
56 | { .rate = 700000000, .cfg0 = 0x800405d1, .cfg1 = 0x04555555 }, | |
57 | { .rate = 800000000, .cfg0 = 0x80040691, .cfg1 = 0x04aaaaaa }, | |
58 | { .rate = 900000000, .cfg0 = 0x80040791, .cfg1 = 0x04000000 }, | |
59 | { .rate = 1000000000, .cfg0 = 0x80040851, .cfg1 = 0x04555555 }, | |
60 | { .rate = 1100000000, .cfg0 = 0x80040911, .cfg1 = 0x04aaaaaa }, | |
61 | { .rate = 1200000000, .cfg0 = 0x80040a11, .cfg1 = 0x04000000 }, | |
62 | }; | |
63 | ||
64 | static const struct clk_div_table main_hlk_div[] = { | |
65 | { .val = 1, .div = 2, }, | |
66 | { .val = 3, .div = 4, }, | |
67 | { /* sentinel */ } | |
68 | }; | |
69 | ||
70 | static const struct clk_div_table a9_as1_aclk_divider[] = { | |
71 | { .val = 0, .div = 1, }, | |
72 | { .val = 1, .div = 2, }, | |
73 | { .val = 3, .div = 4, }, | |
74 | { /* sentinel */ } | |
75 | }; | |
76 | ||
77 | static const struct clk_div_table sec_wclk_divider[] = { | |
78 | { .val = 0, .div = 1, }, | |
79 | { .val = 1, .div = 2, }, | |
80 | { .val = 3, .div = 4, }, | |
81 | { .val = 5, .div = 6, }, | |
82 | { .val = 7, .div = 8, }, | |
83 | { /* sentinel */ } | |
84 | }; | |
85 | ||
d99215ae | 86 | static const char * const matrix_aclk_sel[] = { |
5a465808 JN |
87 | "pll_mm0_198M", |
88 | "osc", | |
89 | "clk_148M5", | |
90 | "pll_lsp_104M", | |
91 | }; | |
92 | ||
d99215ae | 93 | static const char * const a9_wclk_sel[] = { |
5a465808 JN |
94 | "pll_a9", |
95 | "osc", | |
96 | "clk_500", | |
97 | "clk_250", | |
98 | }; | |
99 | ||
d99215ae | 100 | static const char * const a9_as1_aclk_sel[] = { |
5a465808 JN |
101 | "clk_250", |
102 | "osc", | |
103 | "pll_mm0_396M", | |
104 | "pll_mac_333M", | |
105 | }; | |
106 | ||
d99215ae | 107 | static const char * const a9_trace_clkin_sel[] = { |
5a465808 JN |
108 | "clk_74M25", |
109 | "pll_mm1_108M", | |
110 | "clk_125", | |
111 | "clk_148M5", | |
112 | }; | |
113 | ||
d99215ae | 114 | static const char * const decppu_aclk_sel[] = { |
5a465808 JN |
115 | "clk_250", |
116 | "pll_mm0_198M", | |
117 | "pll_lsp_104M", | |
118 | "pll_audio_294M912", | |
119 | }; | |
120 | ||
d99215ae | 121 | static const char * const vou_main_wclk_sel[] = { |
5a465808 JN |
122 | "clk_148M5", |
123 | "clk_74M25", | |
124 | "clk_27", | |
125 | "pll_mm1_54M", | |
126 | }; | |
127 | ||
d99215ae | 128 | static const char * const vou_scaler_wclk_sel[] = { |
5a465808 JN |
129 | "clk_250", |
130 | "pll_mac_333M", | |
131 | "pll_audio_294M912", | |
132 | "pll_mm0_198M", | |
133 | }; | |
134 | ||
d99215ae | 135 | static const char * const r2d_wclk_sel[] = { |
5a465808 JN |
136 | "pll_audio_294M912", |
137 | "pll_mac_333M", | |
138 | "pll_a9_350M", | |
139 | "pll_mm0_396M", | |
140 | }; | |
141 | ||
d99215ae | 142 | static const char * const ddr_wclk_sel[] = { |
5a465808 JN |
143 | "pll_mac_333M", |
144 | "pll_ddr_266M", | |
145 | "pll_audio_294M912", | |
146 | "pll_mm0_198M", | |
147 | }; | |
148 | ||
d99215ae | 149 | static const char * const nand_wclk_sel[] = { |
5a465808 JN |
150 | "pll_lsp_104M", |
151 | "osc", | |
152 | }; | |
153 | ||
d99215ae | 154 | static const char * const lsp_26_wclk_sel[] = { |
5a465808 JN |
155 | "pll_lsp_26M", |
156 | "osc", | |
157 | }; | |
158 | ||
d99215ae | 159 | static const char * const vl0_sel[] = { |
5a465808 JN |
160 | "vou_main_channel_div", |
161 | "vou_aux_channel_div", | |
162 | }; | |
163 | ||
d99215ae | 164 | static const char * const hdmi_sel[] = { |
5a465808 JN |
165 | "vou_main_channel_wclk", |
166 | "vou_aux_channel_wclk", | |
167 | }; | |
168 | ||
d99215ae | 169 | static const char * const sdmmc0_wclk_sel[] = { |
5a465808 JN |
170 | "lsp1_104M_wclk", |
171 | "lsp1_26M_wclk", | |
172 | }; | |
173 | ||
d99215ae | 174 | static const char * const sdmmc1_wclk_sel[] = { |
5a465808 JN |
175 | "lsp0_104M_wclk", |
176 | "lsp0_26M_wclk", | |
177 | }; | |
178 | ||
d99215ae | 179 | static const char * const uart_wclk_sel[] = { |
5a465808 JN |
180 | "lsp1_104M_wclk", |
181 | "lsp1_26M_wclk", | |
182 | }; | |
183 | ||
d99215ae | 184 | static const char * const spdif0_wclk_sel[] = { |
105644e5 JN |
185 | "lsp0_104M_wclk", |
186 | "lsp0_26M_wclk", | |
187 | }; | |
188 | ||
d99215ae | 189 | static const char * const spdif1_wclk_sel[] = { |
105644e5 JN |
190 | "lsp1_104M_wclk", |
191 | "lsp1_26M_wclk", | |
192 | }; | |
193 | ||
d99215ae | 194 | static const char * const i2s_wclk_sel[] = { |
105644e5 JN |
195 | "lsp0_104M_wclk", |
196 | "lsp0_26M_wclk", | |
197 | }; | |
198 | ||
5a465808 JN |
199 | static inline struct clk *zx_divtbl(const char *name, const char *parent, |
200 | void __iomem *reg, u8 shift, u8 width, | |
201 | const struct clk_div_table *table) | |
202 | { | |
203 | return clk_register_divider_table(NULL, name, parent, 0, reg, shift, | |
204 | width, 0, table, ®_lock); | |
205 | } | |
206 | ||
207 | static inline struct clk *zx_div(const char *name, const char *parent, | |
208 | void __iomem *reg, u8 shift, u8 width) | |
209 | { | |
210 | return clk_register_divider(NULL, name, parent, 0, | |
211 | reg, shift, width, 0, ®_lock); | |
212 | } | |
213 | ||
d99215ae | 214 | static inline struct clk *zx_mux(const char *name, const char * const *parents, |
5a465808 JN |
215 | int num_parents, void __iomem *reg, u8 shift, u8 width) |
216 | { | |
217 | return clk_register_mux(NULL, name, parents, num_parents, | |
218 | 0, reg, shift, width, 0, ®_lock); | |
219 | } | |
220 | ||
221 | static inline struct clk *zx_gate(const char *name, const char *parent, | |
222 | void __iomem *reg, u8 shift) | |
223 | { | |
224 | return clk_register_gate(NULL, name, parent, CLK_IGNORE_UNUSED, | |
105644e5 | 225 | reg, shift, CLK_SET_RATE_PARENT, ®_lock); |
5a465808 JN |
226 | } |
227 | ||
228 | static void __init zx296702_top_clocks_init(struct device_node *np) | |
229 | { | |
230 | struct clk **clk = topclk; | |
231 | int i; | |
232 | ||
233 | topcrm_base = of_iomap(np, 0); | |
234 | WARN_ON(!topcrm_base); | |
235 | ||
236 | clk[ZX296702_OSC] = | |
237 | clk_register_fixed_rate(NULL, "osc", NULL, CLK_IS_ROOT, | |
238 | 30000000); | |
239 | clk[ZX296702_PLL_A9] = | |
240 | clk_register_zx_pll("pll_a9", "osc", 0, topcrm_base | |
241 | + 0x01c, pll_a9_config, | |
242 | ARRAY_SIZE(pll_a9_config), ®_lock); | |
243 | ||
244 | /* TODO: pll_a9_350M look like changeble follow a9 pll */ | |
245 | clk[ZX296702_PLL_A9_350M] = | |
246 | clk_register_fixed_rate(NULL, "pll_a9_350M", "osc", 0, | |
247 | 350000000); | |
248 | clk[ZX296702_PLL_MAC_1000M] = | |
249 | clk_register_fixed_rate(NULL, "pll_mac_1000M", "osc", 0, | |
250 | 1000000000); | |
251 | clk[ZX296702_PLL_MAC_333M] = | |
252 | clk_register_fixed_rate(NULL, "pll_mac_333M", "osc", 0, | |
253 | 333000000); | |
254 | clk[ZX296702_PLL_MM0_1188M] = | |
255 | clk_register_fixed_rate(NULL, "pll_mm0_1188M", "osc", 0, | |
256 | 1188000000); | |
257 | clk[ZX296702_PLL_MM0_396M] = | |
258 | clk_register_fixed_rate(NULL, "pll_mm0_396M", "osc", 0, | |
259 | 396000000); | |
260 | clk[ZX296702_PLL_MM0_198M] = | |
261 | clk_register_fixed_rate(NULL, "pll_mm0_198M", "osc", 0, | |
262 | 198000000); | |
263 | clk[ZX296702_PLL_MM1_108M] = | |
264 | clk_register_fixed_rate(NULL, "pll_mm1_108M", "osc", 0, | |
265 | 108000000); | |
266 | clk[ZX296702_PLL_MM1_72M] = | |
267 | clk_register_fixed_rate(NULL, "pll_mm1_72M", "osc", 0, | |
268 | 72000000); | |
269 | clk[ZX296702_PLL_MM1_54M] = | |
270 | clk_register_fixed_rate(NULL, "pll_mm1_54M", "osc", 0, | |
271 | 54000000); | |
272 | clk[ZX296702_PLL_LSP_104M] = | |
273 | clk_register_fixed_rate(NULL, "pll_lsp_104M", "osc", 0, | |
274 | 104000000); | |
275 | clk[ZX296702_PLL_LSP_26M] = | |
276 | clk_register_fixed_rate(NULL, "pll_lsp_26M", "osc", 0, | |
277 | 26000000); | |
278 | clk[ZX296702_PLL_DDR_266M] = | |
279 | clk_register_fixed_rate(NULL, "pll_ddr_266M", "osc", 0, | |
280 | 266000000); | |
281 | clk[ZX296702_PLL_AUDIO_294M912] = | |
282 | clk_register_fixed_rate(NULL, "pll_audio_294M912", "osc", 0, | |
283 | 294912000); | |
284 | ||
285 | /* bus clock */ | |
286 | clk[ZX296702_MATRIX_ACLK] = | |
287 | zx_mux("matrix_aclk", matrix_aclk_sel, | |
288 | ARRAY_SIZE(matrix_aclk_sel), CLK_MUX, 2, 2); | |
289 | clk[ZX296702_MAIN_HCLK] = | |
290 | zx_divtbl("main_hclk", "matrix_aclk", CLK_DIV, 0, 2, | |
291 | main_hlk_div); | |
292 | clk[ZX296702_MAIN_PCLK] = | |
293 | zx_divtbl("main_pclk", "matrix_aclk", CLK_DIV, 2, 2, | |
294 | main_hlk_div); | |
295 | ||
296 | /* cpu clock */ | |
297 | clk[ZX296702_CLK_500] = | |
298 | clk_register_fixed_factor(NULL, "clk_500", "pll_mac_1000M", 0, | |
299 | 1, 2); | |
300 | clk[ZX296702_CLK_250] = | |
301 | clk_register_fixed_factor(NULL, "clk_250", "pll_mac_1000M", 0, | |
302 | 1, 4); | |
303 | clk[ZX296702_CLK_125] = | |
304 | clk_register_fixed_factor(NULL, "clk_125", "clk_250", 0, 1, 2); | |
305 | clk[ZX296702_CLK_148M5] = | |
306 | clk_register_fixed_factor(NULL, "clk_148M5", "pll_mm0_1188M", 0, | |
307 | 1, 8); | |
308 | clk[ZX296702_CLK_74M25] = | |
309 | clk_register_fixed_factor(NULL, "clk_74M25", "pll_mm0_1188M", 0, | |
310 | 1, 16); | |
311 | clk[ZX296702_A9_WCLK] = | |
312 | zx_mux("a9_wclk", a9_wclk_sel, ARRAY_SIZE(a9_wclk_sel), CLK_MUX, | |
313 | 0, 2); | |
314 | clk[ZX296702_A9_AS1_ACLK_MUX] = | |
315 | zx_mux("a9_as1_aclk_mux", a9_as1_aclk_sel, | |
316 | ARRAY_SIZE(a9_as1_aclk_sel), CLK_MUX, 4, 2); | |
317 | clk[ZX296702_A9_TRACE_CLKIN_MUX] = | |
318 | zx_mux("a9_trace_clkin_mux", a9_trace_clkin_sel, | |
319 | ARRAY_SIZE(a9_trace_clkin_sel), CLK_MUX1, 0, 2); | |
320 | clk[ZX296702_A9_AS1_ACLK_DIV] = | |
321 | zx_divtbl("a9_as1_aclk_div", "a9_as1_aclk_mux", CLK_DIV, 4, 2, | |
322 | a9_as1_aclk_divider); | |
323 | ||
324 | /* multi-media clock */ | |
325 | clk[ZX296702_CLK_2] = | |
326 | clk_register_fixed_factor(NULL, "clk_2", "pll_mm1_72M", 0, | |
327 | 1, 36); | |
328 | clk[ZX296702_CLK_27] = | |
329 | clk_register_fixed_factor(NULL, "clk_27", "pll_mm1_54M", 0, | |
330 | 1, 2); | |
331 | clk[ZX296702_DECPPU_ACLK_MUX] = | |
332 | zx_mux("decppu_aclk_mux", decppu_aclk_sel, | |
333 | ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 6, 2); | |
334 | clk[ZX296702_PPU_ACLK_MUX] = | |
335 | zx_mux("ppu_aclk_mux", decppu_aclk_sel, | |
336 | ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 8, 2); | |
337 | clk[ZX296702_MALI400_ACLK_MUX] = | |
338 | zx_mux("mali400_aclk_mux", decppu_aclk_sel, | |
339 | ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 12, 2); | |
340 | clk[ZX296702_VOU_ACLK_MUX] = | |
341 | zx_mux("vou_aclk_mux", decppu_aclk_sel, | |
342 | ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 10, 2); | |
343 | clk[ZX296702_VOU_MAIN_WCLK_MUX] = | |
344 | zx_mux("vou_main_wclk_mux", vou_main_wclk_sel, | |
345 | ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 14, 2); | |
346 | clk[ZX296702_VOU_AUX_WCLK_MUX] = | |
347 | zx_mux("vou_aux_wclk_mux", vou_main_wclk_sel, | |
348 | ARRAY_SIZE(vou_main_wclk_sel), CLK_MUX, 16, 2); | |
349 | clk[ZX296702_VOU_SCALER_WCLK_MUX] = | |
350 | zx_mux("vou_scaler_wclk_mux", vou_scaler_wclk_sel, | |
351 | ARRAY_SIZE(vou_scaler_wclk_sel), CLK_MUX, | |
352 | 18, 2); | |
353 | clk[ZX296702_R2D_ACLK_MUX] = | |
354 | zx_mux("r2d_aclk_mux", decppu_aclk_sel, | |
355 | ARRAY_SIZE(decppu_aclk_sel), CLK_MUX, 20, 2); | |
356 | clk[ZX296702_R2D_WCLK_MUX] = | |
357 | zx_mux("r2d_wclk_mux", r2d_wclk_sel, | |
358 | ARRAY_SIZE(r2d_wclk_sel), CLK_MUX, 22, 2); | |
359 | ||
360 | /* other clock */ | |
361 | clk[ZX296702_CLK_50] = | |
362 | clk_register_fixed_factor(NULL, "clk_50", "pll_mac_1000M", | |
363 | 0, 1, 20); | |
364 | clk[ZX296702_CLK_25] = | |
365 | clk_register_fixed_factor(NULL, "clk_25", "pll_mac_1000M", | |
366 | 0, 1, 40); | |
367 | clk[ZX296702_CLK_12] = | |
368 | clk_register_fixed_factor(NULL, "clk_12", "pll_mm1_72M", | |
369 | 0, 1, 6); | |
370 | clk[ZX296702_CLK_16M384] = | |
371 | clk_register_fixed_factor(NULL, "clk_16M384", | |
372 | "pll_audio_294M912", 0, 1, 18); | |
373 | clk[ZX296702_CLK_32K768] = | |
374 | clk_register_fixed_factor(NULL, "clk_32K768", "clk_16M384", | |
375 | 0, 1, 500); | |
376 | clk[ZX296702_SEC_WCLK_DIV] = | |
377 | zx_divtbl("sec_wclk_div", "pll_lsp_104M", CLK_DIV, 6, 3, | |
378 | sec_wclk_divider); | |
379 | clk[ZX296702_DDR_WCLK_MUX] = | |
380 | zx_mux("ddr_wclk_mux", ddr_wclk_sel, | |
381 | ARRAY_SIZE(ddr_wclk_sel), CLK_MUX, 24, 2); | |
382 | clk[ZX296702_NAND_WCLK_MUX] = | |
383 | zx_mux("nand_wclk_mux", nand_wclk_sel, | |
384 | ARRAY_SIZE(nand_wclk_sel), CLK_MUX, 24, 2); | |
385 | clk[ZX296702_LSP_26_WCLK_MUX] = | |
386 | zx_mux("lsp_26_wclk_mux", lsp_26_wclk_sel, | |
387 | ARRAY_SIZE(lsp_26_wclk_sel), CLK_MUX, 27, 1); | |
388 | ||
389 | /* gates */ | |
390 | clk[ZX296702_A9_AS0_ACLK] = | |
391 | zx_gate("a9_as0_aclk", "matrix_aclk", CLK_EN0, 0); | |
392 | clk[ZX296702_A9_AS1_ACLK] = | |
393 | zx_gate("a9_as1_aclk", "a9_as1_aclk_div", CLK_EN0, 1); | |
394 | clk[ZX296702_A9_TRACE_CLKIN] = | |
395 | zx_gate("a9_trace_clkin", "a9_trace_clkin_mux", CLK_EN0, 2); | |
396 | clk[ZX296702_DECPPU_AXI_M_ACLK] = | |
397 | zx_gate("decppu_axi_m_aclk", "decppu_aclk_mux", CLK_EN0, 3); | |
398 | clk[ZX296702_DECPPU_AHB_S_HCLK] = | |
399 | zx_gate("decppu_ahb_s_hclk", "main_hclk", CLK_EN0, 4); | |
400 | clk[ZX296702_PPU_AXI_M_ACLK] = | |
401 | zx_gate("ppu_axi_m_aclk", "ppu_aclk_mux", CLK_EN0, 5); | |
402 | clk[ZX296702_PPU_AHB_S_HCLK] = | |
403 | zx_gate("ppu_ahb_s_hclk", "main_hclk", CLK_EN0, 6); | |
404 | clk[ZX296702_VOU_AXI_M_ACLK] = | |
405 | zx_gate("vou_axi_m_aclk", "vou_aclk_mux", CLK_EN0, 7); | |
406 | clk[ZX296702_VOU_APB_PCLK] = | |
407 | zx_gate("vou_apb_pclk", "main_pclk", CLK_EN0, 8); | |
408 | clk[ZX296702_VOU_MAIN_CHANNEL_WCLK] = | |
409 | zx_gate("vou_main_channel_wclk", "vou_main_wclk_mux", | |
410 | CLK_EN0, 9); | |
411 | clk[ZX296702_VOU_AUX_CHANNEL_WCLK] = | |
412 | zx_gate("vou_aux_channel_wclk", "vou_aux_wclk_mux", | |
413 | CLK_EN0, 10); | |
414 | clk[ZX296702_VOU_HDMI_OSCLK_CEC] = | |
415 | zx_gate("vou_hdmi_osclk_cec", "clk_2", CLK_EN0, 11); | |
416 | clk[ZX296702_VOU_SCALER_WCLK] = | |
417 | zx_gate("vou_scaler_wclk", "vou_scaler_wclk_mux", CLK_EN0, 12); | |
418 | clk[ZX296702_MALI400_AXI_M_ACLK] = | |
419 | zx_gate("mali400_axi_m_aclk", "mali400_aclk_mux", CLK_EN0, 13); | |
420 | clk[ZX296702_MALI400_APB_PCLK] = | |
421 | zx_gate("mali400_apb_pclk", "main_pclk", CLK_EN0, 14); | |
422 | clk[ZX296702_R2D_WCLK] = | |
423 | zx_gate("r2d_wclk", "r2d_wclk_mux", CLK_EN0, 15); | |
424 | clk[ZX296702_R2D_AXI_M_ACLK] = | |
425 | zx_gate("r2d_axi_m_aclk", "r2d_aclk_mux", CLK_EN0, 16); | |
426 | clk[ZX296702_R2D_AHB_HCLK] = | |
427 | zx_gate("r2d_ahb_hclk", "main_hclk", CLK_EN0, 17); | |
428 | clk[ZX296702_DDR3_AXI_S0_ACLK] = | |
429 | zx_gate("ddr3_axi_s0_aclk", "matrix_aclk", CLK_EN0, 18); | |
430 | clk[ZX296702_DDR3_APB_PCLK] = | |
431 | zx_gate("ddr3_apb_pclk", "main_pclk", CLK_EN0, 19); | |
432 | clk[ZX296702_DDR3_WCLK] = | |
433 | zx_gate("ddr3_wclk", "ddr_wclk_mux", CLK_EN0, 20); | |
434 | clk[ZX296702_USB20_0_AHB_HCLK] = | |
435 | zx_gate("usb20_0_ahb_hclk", "main_hclk", CLK_EN0, 21); | |
436 | clk[ZX296702_USB20_0_EXTREFCLK] = | |
437 | zx_gate("usb20_0_extrefclk", "clk_12", CLK_EN0, 22); | |
438 | clk[ZX296702_USB20_1_AHB_HCLK] = | |
439 | zx_gate("usb20_1_ahb_hclk", "main_hclk", CLK_EN0, 23); | |
440 | clk[ZX296702_USB20_1_EXTREFCLK] = | |
441 | zx_gate("usb20_1_extrefclk", "clk_12", CLK_EN0, 24); | |
442 | clk[ZX296702_USB20_2_AHB_HCLK] = | |
443 | zx_gate("usb20_2_ahb_hclk", "main_hclk", CLK_EN0, 25); | |
444 | clk[ZX296702_USB20_2_EXTREFCLK] = | |
445 | zx_gate("usb20_2_extrefclk", "clk_12", CLK_EN0, 26); | |
446 | clk[ZX296702_GMAC_AXI_M_ACLK] = | |
447 | zx_gate("gmac_axi_m_aclk", "matrix_aclk", CLK_EN0, 27); | |
448 | clk[ZX296702_GMAC_APB_PCLK] = | |
449 | zx_gate("gmac_apb_pclk", "main_pclk", CLK_EN0, 28); | |
450 | clk[ZX296702_GMAC_125_CLKIN] = | |
451 | zx_gate("gmac_125_clkin", "clk_125", CLK_EN0, 29); | |
452 | clk[ZX296702_GMAC_RMII_CLKIN] = | |
453 | zx_gate("gmac_rmii_clkin", "clk_50", CLK_EN0, 30); | |
454 | clk[ZX296702_GMAC_25M_CLK] = | |
455 | zx_gate("gmac_25M_clk", "clk_25", CLK_EN0, 31); | |
456 | clk[ZX296702_NANDFLASH_AHB_HCLK] = | |
457 | zx_gate("nandflash_ahb_hclk", "main_hclk", CLK_EN1, 0); | |
458 | clk[ZX296702_NANDFLASH_WCLK] = | |
459 | zx_gate("nandflash_wclk", "nand_wclk_mux", CLK_EN1, 1); | |
460 | clk[ZX296702_LSP0_APB_PCLK] = | |
461 | zx_gate("lsp0_apb_pclk", "main_pclk", CLK_EN1, 2); | |
462 | clk[ZX296702_LSP0_AHB_HCLK] = | |
463 | zx_gate("lsp0_ahb_hclk", "main_hclk", CLK_EN1, 3); | |
464 | clk[ZX296702_LSP0_26M_WCLK] = | |
465 | zx_gate("lsp0_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 4); | |
466 | clk[ZX296702_LSP0_104M_WCLK] = | |
467 | zx_gate("lsp0_104M_wclk", "pll_lsp_104M", CLK_EN1, 5); | |
468 | clk[ZX296702_LSP0_16M384_WCLK] = | |
469 | zx_gate("lsp0_16M384_wclk", "clk_16M384", CLK_EN1, 6); | |
470 | clk[ZX296702_LSP1_APB_PCLK] = | |
471 | zx_gate("lsp1_apb_pclk", "main_pclk", CLK_EN1, 7); | |
472 | /* FIXME: wclk enable bit is bit8. We hack it as reserved 31 for | |
473 | * UART does not work after parent clk is disabled/enabled */ | |
474 | clk[ZX296702_LSP1_26M_WCLK] = | |
475 | zx_gate("lsp1_26M_wclk", "lsp_26_wclk_mux", CLK_EN1, 31); | |
476 | clk[ZX296702_LSP1_104M_WCLK] = | |
477 | zx_gate("lsp1_104M_wclk", "pll_lsp_104M", CLK_EN1, 9); | |
478 | clk[ZX296702_LSP1_32K_CLK] = | |
479 | zx_gate("lsp1_32K_clk", "clk_32K768", CLK_EN1, 10); | |
480 | clk[ZX296702_AON_HCLK] = | |
481 | zx_gate("aon_hclk", "main_hclk", CLK_EN1, 11); | |
482 | clk[ZX296702_SYS_CTRL_PCLK] = | |
483 | zx_gate("sys_ctrl_pclk", "main_pclk", CLK_EN1, 12); | |
484 | clk[ZX296702_DMA_PCLK] = | |
485 | zx_gate("dma_pclk", "main_pclk", CLK_EN1, 13); | |
486 | clk[ZX296702_DMA_ACLK] = | |
487 | zx_gate("dma_aclk", "matrix_aclk", CLK_EN1, 14); | |
488 | clk[ZX296702_SEC_HCLK] = | |
489 | zx_gate("sec_hclk", "main_hclk", CLK_EN1, 15); | |
490 | clk[ZX296702_AES_WCLK] = | |
491 | zx_gate("aes_wclk", "sec_wclk_div", CLK_EN1, 16); | |
492 | clk[ZX296702_DES_WCLK] = | |
493 | zx_gate("des_wclk", "sec_wclk_div", CLK_EN1, 17); | |
494 | clk[ZX296702_IRAM_ACLK] = | |
495 | zx_gate("iram_aclk", "matrix_aclk", CLK_EN1, 18); | |
496 | clk[ZX296702_IROM_ACLK] = | |
497 | zx_gate("irom_aclk", "matrix_aclk", CLK_EN1, 19); | |
498 | clk[ZX296702_BOOT_CTRL_HCLK] = | |
499 | zx_gate("boot_ctrl_hclk", "main_hclk", CLK_EN1, 20); | |
500 | clk[ZX296702_EFUSE_CLK_30] = | |
501 | zx_gate("efuse_clk_30", "osc", CLK_EN1, 21); | |
502 | ||
503 | /* TODO: add VOU Local clocks */ | |
504 | clk[ZX296702_VOU_MAIN_CHANNEL_DIV] = | |
505 | zx_div("vou_main_channel_div", "vou_main_channel_wclk", | |
506 | VOU_LOCAL_DIV2_SET, 1, 1); | |
507 | clk[ZX296702_VOU_AUX_CHANNEL_DIV] = | |
508 | zx_div("vou_aux_channel_div", "vou_aux_channel_wclk", | |
509 | VOU_LOCAL_DIV2_SET, 0, 1); | |
510 | clk[ZX296702_VOU_TV_ENC_HD_DIV] = | |
511 | zx_div("vou_tv_enc_hd_div", "vou_tv_enc_hd_mux", | |
512 | VOU_LOCAL_DIV2_SET, 3, 1); | |
513 | clk[ZX296702_VOU_TV_ENC_SD_DIV] = | |
514 | zx_div("vou_tv_enc_sd_div", "vou_tv_enc_sd_mux", | |
515 | VOU_LOCAL_DIV2_SET, 2, 1); | |
516 | clk[ZX296702_VL0_MUX] = | |
517 | zx_mux("vl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
518 | VOU_LOCAL_CLKSEL, 8, 1); | |
519 | clk[ZX296702_VL1_MUX] = | |
520 | zx_mux("vl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
521 | VOU_LOCAL_CLKSEL, 9, 1); | |
522 | clk[ZX296702_VL2_MUX] = | |
523 | zx_mux("vl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
524 | VOU_LOCAL_CLKSEL, 10, 1); | |
525 | clk[ZX296702_GL0_MUX] = | |
526 | zx_mux("gl0_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
527 | VOU_LOCAL_CLKSEL, 5, 1); | |
528 | clk[ZX296702_GL1_MUX] = | |
529 | zx_mux("gl1_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
530 | VOU_LOCAL_CLKSEL, 6, 1); | |
531 | clk[ZX296702_GL2_MUX] = | |
532 | zx_mux("gl2_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
533 | VOU_LOCAL_CLKSEL, 7, 1); | |
534 | clk[ZX296702_WB_MUX] = | |
535 | zx_mux("wb_mux", vl0_sel, ARRAY_SIZE(vl0_sel), | |
536 | VOU_LOCAL_CLKSEL, 11, 1); | |
537 | clk[ZX296702_HDMI_MUX] = | |
538 | zx_mux("hdmi_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), | |
539 | VOU_LOCAL_CLKSEL, 4, 1); | |
540 | clk[ZX296702_VOU_TV_ENC_HD_MUX] = | |
541 | zx_mux("vou_tv_enc_hd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), | |
542 | VOU_LOCAL_CLKSEL, 3, 1); | |
543 | clk[ZX296702_VOU_TV_ENC_SD_MUX] = | |
544 | zx_mux("vou_tv_enc_sd_mux", hdmi_sel, ARRAY_SIZE(hdmi_sel), | |
545 | VOU_LOCAL_CLKSEL, 2, 1); | |
546 | clk[ZX296702_VL0_CLK] = | |
547 | zx_gate("vl0_clk", "vl0_mux", VOU_LOCAL_CLKEN, 8); | |
548 | clk[ZX296702_VL1_CLK] = | |
549 | zx_gate("vl1_clk", "vl1_mux", VOU_LOCAL_CLKEN, 9); | |
550 | clk[ZX296702_VL2_CLK] = | |
551 | zx_gate("vl2_clk", "vl2_mux", VOU_LOCAL_CLKEN, 10); | |
552 | clk[ZX296702_GL0_CLK] = | |
553 | zx_gate("gl0_clk", "gl0_mux", VOU_LOCAL_CLKEN, 5); | |
554 | clk[ZX296702_GL1_CLK] = | |
555 | zx_gate("gl1_clk", "gl1_mux", VOU_LOCAL_CLKEN, 6); | |
556 | clk[ZX296702_GL2_CLK] = | |
557 | zx_gate("gl2_clk", "gl2_mux", VOU_LOCAL_CLKEN, 7); | |
558 | clk[ZX296702_WB_CLK] = | |
559 | zx_gate("wb_clk", "wb_mux", VOU_LOCAL_CLKEN, 11); | |
560 | clk[ZX296702_CL_CLK] = | |
561 | zx_gate("cl_clk", "vou_main_channel_div", VOU_LOCAL_CLKEN, 12); | |
562 | clk[ZX296702_MAIN_MIX_CLK] = | |
563 | zx_gate("main_mix_clk", "vou_main_channel_div", | |
564 | VOU_LOCAL_CLKEN, 4); | |
565 | clk[ZX296702_AUX_MIX_CLK] = | |
566 | zx_gate("aux_mix_clk", "vou_aux_channel_div", | |
567 | VOU_LOCAL_CLKEN, 3); | |
568 | clk[ZX296702_HDMI_CLK] = | |
569 | zx_gate("hdmi_clk", "hdmi_mux", VOU_LOCAL_CLKEN, 2); | |
570 | clk[ZX296702_VOU_TV_ENC_HD_DAC_CLK] = | |
571 | zx_gate("vou_tv_enc_hd_dac_clk", "vou_tv_enc_hd_div", | |
572 | VOU_LOCAL_CLKEN, 1); | |
573 | clk[ZX296702_VOU_TV_ENC_SD_DAC_CLK] = | |
574 | zx_gate("vou_tv_enc_sd_dac_clk", "vou_tv_enc_sd_div", | |
575 | VOU_LOCAL_CLKEN, 0); | |
576 | ||
577 | /* CA9 PERIPHCLK = a9_wclk / 2 */ | |
578 | clk[ZX296702_A9_PERIPHCLK] = | |
579 | clk_register_fixed_factor(NULL, "a9_periphclk", "a9_wclk", | |
580 | 0, 1, 2); | |
581 | ||
582 | for (i = 0; i < ARRAY_SIZE(topclk); i++) { | |
583 | if (IS_ERR(clk[i])) { | |
584 | pr_err("zx296702 clk %d: register failed with %ld\n", | |
585 | i, PTR_ERR(clk[i])); | |
586 | return; | |
587 | } | |
588 | } | |
589 | ||
590 | topclk_data.clks = topclk; | |
591 | topclk_data.clk_num = ARRAY_SIZE(topclk); | |
592 | of_clk_add_provider(np, of_clk_src_onecell_get, &topclk_data); | |
593 | } | |
594 | CLK_OF_DECLARE(zx296702_top_clk, "zte,zx296702-topcrm-clk", | |
595 | zx296702_top_clocks_init); | |
596 | ||
597 | static void __init zx296702_lsp0_clocks_init(struct device_node *np) | |
598 | { | |
599 | struct clk **clk = lsp0clk; | |
600 | int i; | |
601 | ||
602 | lsp0crpm_base = of_iomap(np, 0); | |
603 | WARN_ON(!lsp0crpm_base); | |
604 | ||
605 | /* SDMMC1 */ | |
606 | clk[ZX296702_SDMMC1_WCLK_MUX] = | |
607 | zx_mux("sdmmc1_wclk_mux", sdmmc1_wclk_sel, | |
608 | ARRAY_SIZE(sdmmc1_wclk_sel), CLK_SDMMC1, 4, 1); | |
609 | clk[ZX296702_SDMMC1_WCLK_DIV] = | |
610 | zx_div("sdmmc1_wclk_div", "sdmmc1_wclk_mux", CLK_SDMMC1, 12, 4); | |
611 | clk[ZX296702_SDMMC1_WCLK] = | |
612 | zx_gate("sdmmc1_wclk", "sdmmc1_wclk_div", CLK_SDMMC1, 1); | |
613 | clk[ZX296702_SDMMC1_PCLK] = | |
105644e5 JN |
614 | zx_gate("sdmmc1_pclk", "lsp0_apb_pclk", CLK_SDMMC1, 0); |
615 | ||
616 | clk[ZX296702_GPIO_CLK] = | |
617 | zx_gate("gpio_clk", "lsp0_apb_pclk", CLK_GPIO, 0); | |
618 | ||
619 | /* SPDIF */ | |
620 | clk[ZX296702_SPDIF0_WCLK_MUX] = | |
621 | zx_mux("spdif0_wclk_mux", spdif0_wclk_sel, | |
622 | ARRAY_SIZE(spdif0_wclk_sel), CLK_SPDIF0, 4, 1); | |
623 | clk[ZX296702_SPDIF0_WCLK] = | |
624 | zx_gate("spdif0_wclk", "spdif0_wclk_mux", CLK_SPDIF0, 1); | |
625 | clk[ZX296702_SPDIF0_PCLK] = | |
626 | zx_gate("spdif0_pclk", "lsp0_apb_pclk", CLK_SPDIF0, 0); | |
627 | ||
628 | clk[ZX296702_SPDIF0_DIV] = | |
629 | clk_register_zx_audio("spdif0_div", "spdif0_wclk", 0, | |
630 | SPDIF0_DIV); | |
631 | ||
632 | /* I2S */ | |
633 | clk[ZX296702_I2S0_WCLK_MUX] = | |
634 | zx_mux("i2s0_wclk_mux", i2s_wclk_sel, | |
635 | ARRAY_SIZE(i2s_wclk_sel), CLK_I2S0, 4, 1); | |
636 | clk[ZX296702_I2S0_WCLK] = | |
637 | zx_gate("i2s0_wclk", "i2s0_wclk_mux", CLK_I2S0, 1); | |
638 | clk[ZX296702_I2S0_PCLK] = | |
639 | zx_gate("i2s0_pclk", "lsp0_apb_pclk", CLK_I2S0, 0); | |
640 | ||
641 | clk[ZX296702_I2S0_DIV] = | |
642 | clk_register_zx_audio("i2s0_div", "i2s0_wclk", 0, I2S0_DIV); | |
643 | ||
644 | clk[ZX296702_I2S1_WCLK_MUX] = | |
645 | zx_mux("i2s1_wclk_mux", i2s_wclk_sel, | |
646 | ARRAY_SIZE(i2s_wclk_sel), CLK_I2S1, 4, 1); | |
647 | clk[ZX296702_I2S1_WCLK] = | |
648 | zx_gate("i2s1_wclk", "i2s1_wclk_mux", CLK_I2S1, 1); | |
649 | clk[ZX296702_I2S1_PCLK] = | |
650 | zx_gate("i2s1_pclk", "lsp0_apb_pclk", CLK_I2S1, 0); | |
651 | ||
652 | clk[ZX296702_I2S1_DIV] = | |
653 | clk_register_zx_audio("i2s1_div", "i2s1_wclk", 0, I2S1_DIV); | |
654 | ||
655 | clk[ZX296702_I2S2_WCLK_MUX] = | |
656 | zx_mux("i2s2_wclk_mux", i2s_wclk_sel, | |
657 | ARRAY_SIZE(i2s_wclk_sel), CLK_I2S2, 4, 1); | |
658 | clk[ZX296702_I2S2_WCLK] = | |
659 | zx_gate("i2s2_wclk", "i2s2_wclk_mux", CLK_I2S2, 1); | |
660 | clk[ZX296702_I2S2_PCLK] = | |
661 | zx_gate("i2s2_pclk", "lsp0_apb_pclk", CLK_I2S2, 0); | |
662 | ||
663 | clk[ZX296702_I2S2_DIV] = | |
664 | clk_register_zx_audio("i2s2_div", "i2s2_wclk", 0, I2S2_DIV); | |
5a465808 JN |
665 | |
666 | for (i = 0; i < ARRAY_SIZE(lsp0clk); i++) { | |
667 | if (IS_ERR(clk[i])) { | |
668 | pr_err("zx296702 clk %d: register failed with %ld\n", | |
669 | i, PTR_ERR(clk[i])); | |
670 | return; | |
671 | } | |
672 | } | |
673 | ||
674 | lsp0clk_data.clks = lsp0clk; | |
675 | lsp0clk_data.clk_num = ARRAY_SIZE(lsp0clk); | |
676 | of_clk_add_provider(np, of_clk_src_onecell_get, &lsp0clk_data); | |
677 | } | |
678 | CLK_OF_DECLARE(zx296702_lsp0_clk, "zte,zx296702-lsp0crpm-clk", | |
679 | zx296702_lsp0_clocks_init); | |
680 | ||
681 | static void __init zx296702_lsp1_clocks_init(struct device_node *np) | |
682 | { | |
683 | struct clk **clk = lsp1clk; | |
684 | int i; | |
685 | ||
686 | lsp1crpm_base = of_iomap(np, 0); | |
687 | WARN_ON(!lsp1crpm_base); | |
688 | ||
689 | /* UART0 */ | |
690 | clk[ZX296702_UART0_WCLK_MUX] = | |
691 | zx_mux("uart0_wclk_mux", uart_wclk_sel, | |
692 | ARRAY_SIZE(uart_wclk_sel), CLK_UART0, 4, 1); | |
693 | /* FIXME: uart wclk enable bit is bit1 in. We hack it as reserved 31 for | |
694 | * UART does not work after parent clk is disabled/enabled */ | |
695 | clk[ZX296702_UART0_WCLK] = | |
696 | zx_gate("uart0_wclk", "uart0_wclk_mux", CLK_UART0, 31); | |
697 | clk[ZX296702_UART0_PCLK] = | |
698 | zx_gate("uart0_pclk", "lsp1_apb_pclk", CLK_UART0, 0); | |
699 | ||
700 | /* UART1 */ | |
701 | clk[ZX296702_UART1_WCLK_MUX] = | |
702 | zx_mux("uart1_wclk_mux", uart_wclk_sel, | |
703 | ARRAY_SIZE(uart_wclk_sel), CLK_UART1, 4, 1); | |
704 | clk[ZX296702_UART1_WCLK] = | |
705 | zx_gate("uart1_wclk", "uart1_wclk_mux", CLK_UART1, 1); | |
706 | clk[ZX296702_UART1_PCLK] = | |
707 | zx_gate("uart1_pclk", "lsp1_apb_pclk", CLK_UART1, 0); | |
708 | ||
709 | /* SDMMC0 */ | |
710 | clk[ZX296702_SDMMC0_WCLK_MUX] = | |
711 | zx_mux("sdmmc0_wclk_mux", sdmmc0_wclk_sel, | |
712 | ARRAY_SIZE(sdmmc0_wclk_sel), CLK_SDMMC0, 4, 1); | |
713 | clk[ZX296702_SDMMC0_WCLK_DIV] = | |
714 | zx_div("sdmmc0_wclk_div", "sdmmc0_wclk_mux", CLK_SDMMC0, 12, 4); | |
715 | clk[ZX296702_SDMMC0_WCLK] = | |
716 | zx_gate("sdmmc0_wclk", "sdmmc0_wclk_div", CLK_SDMMC0, 1); | |
717 | clk[ZX296702_SDMMC0_PCLK] = | |
718 | zx_gate("sdmmc0_pclk", "lsp1_apb_pclk", CLK_SDMMC0, 0); | |
719 | ||
105644e5 JN |
720 | clk[ZX296702_SPDIF1_WCLK_MUX] = |
721 | zx_mux("spdif1_wclk_mux", spdif1_wclk_sel, | |
722 | ARRAY_SIZE(spdif1_wclk_sel), CLK_SPDIF1, 4, 1); | |
723 | clk[ZX296702_SPDIF1_WCLK] = | |
724 | zx_gate("spdif1_wclk", "spdif1_wclk_mux", CLK_SPDIF1, 1); | |
725 | clk[ZX296702_SPDIF1_PCLK] = | |
726 | zx_gate("spdif1_pclk", "lsp1_apb_pclk", CLK_SPDIF1, 0); | |
727 | ||
728 | clk[ZX296702_SPDIF1_DIV] = | |
729 | clk_register_zx_audio("spdif1_div", "spdif1_wclk", 0, | |
730 | SPDIF1_DIV); | |
731 | ||
5a465808 JN |
732 | for (i = 0; i < ARRAY_SIZE(lsp1clk); i++) { |
733 | if (IS_ERR(clk[i])) { | |
734 | pr_err("zx296702 clk %d: register failed with %ld\n", | |
735 | i, PTR_ERR(clk[i])); | |
736 | return; | |
737 | } | |
738 | } | |
739 | ||
740 | lsp1clk_data.clks = lsp1clk; | |
741 | lsp1clk_data.clk_num = ARRAY_SIZE(lsp1clk); | |
742 | of_clk_add_provider(np, of_clk_src_onecell_get, &lsp1clk_data); | |
743 | } | |
744 | CLK_OF_DECLARE(zx296702_lsp1_clk, "zte,zx296702-lsp1crpm-clk", | |
745 | zx296702_lsp1_clocks_init); |