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