diff options
Diffstat (limited to 'drivers/clk/meson/axg.c')
-rw-r--r-- | drivers/clk/meson/axg.c | 955 |
1 files changed, 542 insertions, 413 deletions
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c index 1294f3ad7cd5..5f5d468c1efe 100644 --- a/drivers/clk/meson/axg.c +++ b/drivers/clk/meson/axg.c | |||
@@ -11,125 +11,51 @@ | |||
11 | 11 | ||
12 | #include <linux/clk.h> | 12 | #include <linux/clk.h> |
13 | #include <linux/clk-provider.h> | 13 | #include <linux/clk-provider.h> |
14 | #include <linux/init.h> | ||
14 | #include <linux/of_address.h> | 15 | #include <linux/of_address.h> |
15 | #include <linux/of_device.h> | 16 | #include <linux/of_device.h> |
17 | #include <linux/mfd/syscon.h> | ||
16 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
17 | #include <linux/init.h> | 19 | #include <linux/regmap.h> |
18 | 20 | ||
19 | #include "clkc.h" | 21 | #include "clkc.h" |
20 | #include "axg.h" | 22 | #include "axg.h" |
21 | 23 | ||
22 | static DEFINE_SPINLOCK(meson_clk_lock); | 24 | static DEFINE_SPINLOCK(meson_clk_lock); |
23 | 25 | ||
24 | static const struct pll_rate_table sys_pll_rate_table[] = { | 26 | static struct clk_regmap axg_fixed_pll = { |
25 | PLL_RATE(24000000, 56, 1, 2), | 27 | .data = &(struct meson_clk_pll_data){ |
26 | PLL_RATE(48000000, 64, 1, 2), | 28 | .m = { |
27 | PLL_RATE(72000000, 72, 1, 2), | 29 | .reg_off = HHI_MPLL_CNTL, |
28 | PLL_RATE(96000000, 64, 1, 2), | 30 | .shift = 0, |
29 | PLL_RATE(120000000, 80, 1, 2), | 31 | .width = 9, |
30 | PLL_RATE(144000000, 96, 1, 2), | 32 | }, |
31 | PLL_RATE(168000000, 56, 1, 1), | 33 | .n = { |
32 | PLL_RATE(192000000, 64, 1, 1), | 34 | .reg_off = HHI_MPLL_CNTL, |
33 | PLL_RATE(216000000, 72, 1, 1), | 35 | .shift = 9, |
34 | PLL_RATE(240000000, 80, 1, 1), | 36 | .width = 5, |
35 | PLL_RATE(264000000, 88, 1, 1), | 37 | }, |
36 | PLL_RATE(288000000, 96, 1, 1), | 38 | .od = { |
37 | PLL_RATE(312000000, 52, 1, 2), | 39 | .reg_off = HHI_MPLL_CNTL, |
38 | PLL_RATE(336000000, 56, 1, 2), | 40 | .shift = 16, |
39 | PLL_RATE(360000000, 60, 1, 2), | 41 | .width = 2, |
40 | PLL_RATE(384000000, 64, 1, 2), | 42 | }, |
41 | PLL_RATE(408000000, 68, 1, 2), | 43 | .frac = { |
42 | PLL_RATE(432000000, 72, 1, 2), | 44 | .reg_off = HHI_MPLL_CNTL2, |
43 | PLL_RATE(456000000, 76, 1, 2), | 45 | .shift = 0, |
44 | PLL_RATE(480000000, 80, 1, 2), | 46 | .width = 12, |
45 | PLL_RATE(504000000, 84, 1, 2), | 47 | }, |
46 | PLL_RATE(528000000, 88, 1, 2), | 48 | .l = { |
47 | PLL_RATE(552000000, 92, 1, 2), | 49 | .reg_off = HHI_MPLL_CNTL, |
48 | PLL_RATE(576000000, 96, 1, 2), | 50 | .shift = 31, |
49 | PLL_RATE(600000000, 50, 1, 1), | 51 | .width = 1, |
50 | PLL_RATE(624000000, 52, 1, 1), | 52 | }, |
51 | PLL_RATE(648000000, 54, 1, 1), | 53 | .rst = { |
52 | PLL_RATE(672000000, 56, 1, 1), | 54 | .reg_off = HHI_MPLL_CNTL, |
53 | PLL_RATE(696000000, 58, 1, 1), | 55 | .shift = 29, |
54 | PLL_RATE(720000000, 60, 1, 1), | 56 | .width = 1, |
55 | PLL_RATE(744000000, 62, 1, 1), | 57 | }, |
56 | PLL_RATE(768000000, 64, 1, 1), | ||
57 | PLL_RATE(792000000, 66, 1, 1), | ||
58 | PLL_RATE(816000000, 68, 1, 1), | ||
59 | PLL_RATE(840000000, 70, 1, 1), | ||
60 | PLL_RATE(864000000, 72, 1, 1), | ||
61 | PLL_RATE(888000000, 74, 1, 1), | ||
62 | PLL_RATE(912000000, 76, 1, 1), | ||
63 | PLL_RATE(936000000, 78, 1, 1), | ||
64 | PLL_RATE(960000000, 80, 1, 1), | ||
65 | PLL_RATE(984000000, 82, 1, 1), | ||
66 | PLL_RATE(1008000000, 84, 1, 1), | ||
67 | PLL_RATE(1032000000, 86, 1, 1), | ||
68 | PLL_RATE(1056000000, 88, 1, 1), | ||
69 | PLL_RATE(1080000000, 90, 1, 1), | ||
70 | PLL_RATE(1104000000, 92, 1, 1), | ||
71 | PLL_RATE(1128000000, 94, 1, 1), | ||
72 | PLL_RATE(1152000000, 96, 1, 1), | ||
73 | PLL_RATE(1176000000, 98, 1, 1), | ||
74 | PLL_RATE(1200000000, 50, 1, 0), | ||
75 | PLL_RATE(1224000000, 51, 1, 0), | ||
76 | PLL_RATE(1248000000, 52, 1, 0), | ||
77 | PLL_RATE(1272000000, 53, 1, 0), | ||
78 | PLL_RATE(1296000000, 54, 1, 0), | ||
79 | PLL_RATE(1320000000, 55, 1, 0), | ||
80 | PLL_RATE(1344000000, 56, 1, 0), | ||
81 | PLL_RATE(1368000000, 57, 1, 0), | ||
82 | PLL_RATE(1392000000, 58, 1, 0), | ||
83 | PLL_RATE(1416000000, 59, 1, 0), | ||
84 | PLL_RATE(1440000000, 60, 1, 0), | ||
85 | PLL_RATE(1464000000, 61, 1, 0), | ||
86 | PLL_RATE(1488000000, 62, 1, 0), | ||
87 | PLL_RATE(1512000000, 63, 1, 0), | ||
88 | PLL_RATE(1536000000, 64, 1, 0), | ||
89 | PLL_RATE(1560000000, 65, 1, 0), | ||
90 | PLL_RATE(1584000000, 66, 1, 0), | ||
91 | PLL_RATE(1608000000, 67, 1, 0), | ||
92 | PLL_RATE(1632000000, 68, 1, 0), | ||
93 | PLL_RATE(1656000000, 68, 1, 0), | ||
94 | PLL_RATE(1680000000, 68, 1, 0), | ||
95 | PLL_RATE(1704000000, 68, 1, 0), | ||
96 | PLL_RATE(1728000000, 69, 1, 0), | ||
97 | PLL_RATE(1752000000, 69, 1, 0), | ||
98 | PLL_RATE(1776000000, 69, 1, 0), | ||
99 | PLL_RATE(1800000000, 69, 1, 0), | ||
100 | PLL_RATE(1824000000, 70, 1, 0), | ||
101 | PLL_RATE(1848000000, 70, 1, 0), | ||
102 | PLL_RATE(1872000000, 70, 1, 0), | ||
103 | PLL_RATE(1896000000, 70, 1, 0), | ||
104 | PLL_RATE(1920000000, 71, 1, 0), | ||
105 | PLL_RATE(1944000000, 71, 1, 0), | ||
106 | PLL_RATE(1968000000, 71, 1, 0), | ||
107 | PLL_RATE(1992000000, 71, 1, 0), | ||
108 | PLL_RATE(2016000000, 72, 1, 0), | ||
109 | PLL_RATE(2040000000, 72, 1, 0), | ||
110 | PLL_RATE(2064000000, 72, 1, 0), | ||
111 | PLL_RATE(2088000000, 72, 1, 0), | ||
112 | PLL_RATE(2112000000, 73, 1, 0), | ||
113 | { /* sentinel */ }, | ||
114 | }; | ||
115 | |||
116 | static struct meson_clk_pll axg_fixed_pll = { | ||
117 | .m = { | ||
118 | .reg_off = HHI_MPLL_CNTL, | ||
119 | .shift = 0, | ||
120 | .width = 9, | ||
121 | }, | ||
122 | .n = { | ||
123 | .reg_off = HHI_MPLL_CNTL, | ||
124 | .shift = 9, | ||
125 | .width = 5, | ||
126 | }, | ||
127 | .od = { | ||
128 | .reg_off = HHI_MPLL_CNTL, | ||
129 | .shift = 16, | ||
130 | .width = 2, | ||
131 | }, | 58 | }, |
132 | .lock = &meson_clk_lock, | ||
133 | .hw.init = &(struct clk_init_data){ | 59 | .hw.init = &(struct clk_init_data){ |
134 | .name = "fixed_pll", | 60 | .name = "fixed_pll", |
135 | .ops = &meson_clk_pll_ro_ops, | 61 | .ops = &meson_clk_pll_ro_ops, |
@@ -138,25 +64,34 @@ static struct meson_clk_pll axg_fixed_pll = { | |||
138 | }, | 64 | }, |
139 | }; | 65 | }; |
140 | 66 | ||
141 | static struct meson_clk_pll axg_sys_pll = { | 67 | static struct clk_regmap axg_sys_pll = { |
142 | .m = { | 68 | .data = &(struct meson_clk_pll_data){ |
143 | .reg_off = HHI_SYS_PLL_CNTL, | 69 | .m = { |
144 | .shift = 0, | 70 | .reg_off = HHI_SYS_PLL_CNTL, |
145 | .width = 9, | 71 | .shift = 0, |
72 | .width = 9, | ||
73 | }, | ||
74 | .n = { | ||
75 | .reg_off = HHI_SYS_PLL_CNTL, | ||
76 | .shift = 9, | ||
77 | .width = 5, | ||
78 | }, | ||
79 | .od = { | ||
80 | .reg_off = HHI_SYS_PLL_CNTL, | ||
81 | .shift = 16, | ||
82 | .width = 2, | ||
83 | }, | ||
84 | .l = { | ||
85 | .reg_off = HHI_SYS_PLL_CNTL, | ||
86 | .shift = 31, | ||
87 | .width = 1, | ||
88 | }, | ||
89 | .rst = { | ||
90 | .reg_off = HHI_SYS_PLL_CNTL, | ||
91 | .shift = 29, | ||
92 | .width = 1, | ||
93 | }, | ||
146 | }, | 94 | }, |
147 | .n = { | ||
148 | .reg_off = HHI_SYS_PLL_CNTL, | ||
149 | .shift = 9, | ||
150 | .width = 5, | ||
151 | }, | ||
152 | .od = { | ||
153 | .reg_off = HHI_SYS_PLL_CNTL, | ||
154 | .shift = 10, | ||
155 | .width = 2, | ||
156 | }, | ||
157 | .rate_table = sys_pll_rate_table, | ||
158 | .rate_count = ARRAY_SIZE(sys_pll_rate_table), | ||
159 | .lock = &meson_clk_lock, | ||
160 | .hw.init = &(struct clk_init_data){ | 95 | .hw.init = &(struct clk_init_data){ |
161 | .name = "sys_pll", | 96 | .name = "sys_pll", |
162 | .ops = &meson_clk_pll_ro_ops, | 97 | .ops = &meson_clk_pll_ro_ops, |
@@ -257,40 +192,51 @@ static const struct pll_rate_table axg_gp0_pll_rate_table[] = { | |||
257 | { /* sentinel */ }, | 192 | { /* sentinel */ }, |
258 | }; | 193 | }; |
259 | 194 | ||
260 | static struct pll_params_table axg_gp0_params_table[] = { | 195 | static const struct reg_sequence axg_gp0_init_regs[] = { |
261 | PLL_PARAM(HHI_GP0_PLL_CNTL, 0x40010250), | 196 | { .reg = HHI_GP0_PLL_CNTL1, .def = 0xc084b000 }, |
262 | PLL_PARAM(HHI_GP0_PLL_CNTL1, 0xc084a000), | 197 | { .reg = HHI_GP0_PLL_CNTL2, .def = 0xb75020be }, |
263 | PLL_PARAM(HHI_GP0_PLL_CNTL2, 0xb75020be), | 198 | { .reg = HHI_GP0_PLL_CNTL3, .def = 0x0a59a288 }, |
264 | PLL_PARAM(HHI_GP0_PLL_CNTL3, 0x0a59a288), | 199 | { .reg = HHI_GP0_PLL_CNTL4, .def = 0xc000004d }, |
265 | PLL_PARAM(HHI_GP0_PLL_CNTL4, 0xc000004d), | 200 | { .reg = HHI_GP0_PLL_CNTL5, .def = 0x00078000 }, |
266 | PLL_PARAM(HHI_GP0_PLL_CNTL5, 0x00078000), | 201 | { .reg = HHI_GP0_PLL_CNTL, .def = 0x40010250 }, |
267 | }; | 202 | }; |
268 | 203 | ||
269 | static struct meson_clk_pll axg_gp0_pll = { | 204 | static struct clk_regmap axg_gp0_pll = { |
270 | .m = { | 205 | .data = &(struct meson_clk_pll_data){ |
271 | .reg_off = HHI_GP0_PLL_CNTL, | 206 | .m = { |
272 | .shift = 0, | 207 | .reg_off = HHI_GP0_PLL_CNTL, |
273 | .width = 9, | 208 | .shift = 0, |
274 | }, | 209 | .width = 9, |
275 | .n = { | 210 | }, |
276 | .reg_off = HHI_GP0_PLL_CNTL, | 211 | .n = { |
277 | .shift = 9, | 212 | .reg_off = HHI_GP0_PLL_CNTL, |
278 | .width = 5, | 213 | .shift = 9, |
279 | }, | 214 | .width = 5, |
280 | .od = { | 215 | }, |
281 | .reg_off = HHI_GP0_PLL_CNTL, | 216 | .od = { |
282 | .shift = 16, | 217 | .reg_off = HHI_GP0_PLL_CNTL, |
283 | .width = 2, | 218 | .shift = 16, |
284 | }, | 219 | .width = 2, |
285 | .params = { | 220 | }, |
286 | .params_table = axg_gp0_params_table, | 221 | .frac = { |
287 | .params_count = ARRAY_SIZE(axg_gp0_params_table), | 222 | .reg_off = HHI_GP0_PLL_CNTL1, |
288 | .no_init_reset = true, | 223 | .shift = 0, |
289 | .reset_lock_loop = true, | 224 | .width = 10, |
290 | }, | 225 | }, |
291 | .rate_table = axg_gp0_pll_rate_table, | 226 | .l = { |
292 | .rate_count = ARRAY_SIZE(axg_gp0_pll_rate_table), | 227 | .reg_off = HHI_GP0_PLL_CNTL, |
293 | .lock = &meson_clk_lock, | 228 | .shift = 31, |
229 | .width = 1, | ||
230 | }, | ||
231 | .rst = { | ||
232 | .reg_off = HHI_GP0_PLL_CNTL, | ||
233 | .shift = 29, | ||
234 | .width = 1, | ||
235 | }, | ||
236 | .table = axg_gp0_pll_rate_table, | ||
237 | .init_regs = axg_gp0_init_regs, | ||
238 | .init_count = ARRAY_SIZE(axg_gp0_init_regs), | ||
239 | }, | ||
294 | .hw.init = &(struct clk_init_data){ | 240 | .hw.init = &(struct clk_init_data){ |
295 | .name = "gp0_pll", | 241 | .name = "gp0_pll", |
296 | .ops = &meson_clk_pll_ops, | 242 | .ops = &meson_clk_pll_ops, |
@@ -299,234 +245,427 @@ static struct meson_clk_pll axg_gp0_pll = { | |||
299 | }, | 245 | }, |
300 | }; | 246 | }; |
301 | 247 | ||
248 | static const struct reg_sequence axg_hifi_init_regs[] = { | ||
249 | { .reg = HHI_HIFI_PLL_CNTL1, .def = 0xc084b000 }, | ||
250 | { .reg = HHI_HIFI_PLL_CNTL2, .def = 0xb75020be }, | ||
251 | { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x0a6a3a88 }, | ||
252 | { .reg = HHI_HIFI_PLL_CNTL4, .def = 0xc000004d }, | ||
253 | { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x00058000 }, | ||
254 | { .reg = HHI_HIFI_PLL_CNTL, .def = 0x40010250 }, | ||
255 | }; | ||
256 | |||
257 | static struct clk_regmap axg_hifi_pll = { | ||
258 | .data = &(struct meson_clk_pll_data){ | ||
259 | .m = { | ||
260 | .reg_off = HHI_HIFI_PLL_CNTL, | ||
261 | .shift = 0, | ||
262 | .width = 9, | ||
263 | }, | ||
264 | .n = { | ||
265 | .reg_off = HHI_HIFI_PLL_CNTL, | ||
266 | .shift = 9, | ||
267 | .width = 5, | ||
268 | }, | ||
269 | .od = { | ||
270 | .reg_off = HHI_HIFI_PLL_CNTL, | ||
271 | .shift = 16, | ||
272 | .width = 2, | ||
273 | }, | ||
274 | .frac = { | ||
275 | .reg_off = HHI_HIFI_PLL_CNTL5, | ||
276 | .shift = 0, | ||
277 | .width = 13, | ||
278 | }, | ||
279 | .l = { | ||
280 | .reg_off = HHI_HIFI_PLL_CNTL, | ||
281 | .shift = 31, | ||
282 | .width = 1, | ||
283 | }, | ||
284 | .rst = { | ||
285 | .reg_off = HHI_HIFI_PLL_CNTL, | ||
286 | .shift = 29, | ||
287 | .width = 1, | ||
288 | }, | ||
289 | .table = axg_gp0_pll_rate_table, | ||
290 | .init_regs = axg_hifi_init_regs, | ||
291 | .init_count = ARRAY_SIZE(axg_hifi_init_regs), | ||
292 | .flags = CLK_MESON_PLL_ROUND_CLOSEST, | ||
293 | }, | ||
294 | .hw.init = &(struct clk_init_data){ | ||
295 | .name = "hifi_pll", | ||
296 | .ops = &meson_clk_pll_ops, | ||
297 | .parent_names = (const char *[]){ "xtal" }, | ||
298 | .num_parents = 1, | ||
299 | }, | ||
300 | }; | ||
302 | 301 | ||
303 | static struct clk_fixed_factor axg_fclk_div2 = { | 302 | static struct clk_fixed_factor axg_fclk_div2_div = { |
304 | .mult = 1, | 303 | .mult = 1, |
305 | .div = 2, | 304 | .div = 2, |
306 | .hw.init = &(struct clk_init_data){ | 305 | .hw.init = &(struct clk_init_data){ |
307 | .name = "fclk_div2", | 306 | .name = "fclk_div2_div", |
308 | .ops = &clk_fixed_factor_ops, | 307 | .ops = &clk_fixed_factor_ops, |
309 | .parent_names = (const char *[]){ "fixed_pll" }, | 308 | .parent_names = (const char *[]){ "fixed_pll" }, |
310 | .num_parents = 1, | 309 | .num_parents = 1, |
311 | }, | 310 | }, |
312 | }; | 311 | }; |
313 | 312 | ||
314 | static struct clk_fixed_factor axg_fclk_div3 = { | 313 | static struct clk_regmap axg_fclk_div2 = { |
314 | .data = &(struct clk_regmap_gate_data){ | ||
315 | .offset = HHI_MPLL_CNTL6, | ||
316 | .bit_idx = 27, | ||
317 | }, | ||
318 | .hw.init = &(struct clk_init_data){ | ||
319 | .name = "fclk_div2", | ||
320 | .ops = &clk_regmap_gate_ops, | ||
321 | .parent_names = (const char *[]){ "fclk_div2_div" }, | ||
322 | .num_parents = 1, | ||
323 | }, | ||
324 | }; | ||
325 | |||
326 | static struct clk_fixed_factor axg_fclk_div3_div = { | ||
315 | .mult = 1, | 327 | .mult = 1, |
316 | .div = 3, | 328 | .div = 3, |
317 | .hw.init = &(struct clk_init_data){ | 329 | .hw.init = &(struct clk_init_data){ |
318 | .name = "fclk_div3", | 330 | .name = "fclk_div3_div", |
319 | .ops = &clk_fixed_factor_ops, | 331 | .ops = &clk_fixed_factor_ops, |
320 | .parent_names = (const char *[]){ "fixed_pll" }, | 332 | .parent_names = (const char *[]){ "fixed_pll" }, |
321 | .num_parents = 1, | 333 | .num_parents = 1, |
322 | }, | 334 | }, |
323 | }; | 335 | }; |
324 | 336 | ||
325 | static struct clk_fixed_factor axg_fclk_div4 = { | 337 | static struct clk_regmap axg_fclk_div3 = { |
338 | .data = &(struct clk_regmap_gate_data){ | ||
339 | .offset = HHI_MPLL_CNTL6, | ||
340 | .bit_idx = 28, | ||
341 | }, | ||
342 | .hw.init = &(struct clk_init_data){ | ||
343 | .name = "fclk_div3", | ||
344 | .ops = &clk_regmap_gate_ops, | ||
345 | .parent_names = (const char *[]){ "fclk_div3_div" }, | ||
346 | .num_parents = 1, | ||
347 | }, | ||
348 | }; | ||
349 | |||
350 | static struct clk_fixed_factor axg_fclk_div4_div = { | ||
326 | .mult = 1, | 351 | .mult = 1, |
327 | .div = 4, | 352 | .div = 4, |
328 | .hw.init = &(struct clk_init_data){ | 353 | .hw.init = &(struct clk_init_data){ |
329 | .name = "fclk_div4", | 354 | .name = "fclk_div4_div", |
330 | .ops = &clk_fixed_factor_ops, | 355 | .ops = &clk_fixed_factor_ops, |
331 | .parent_names = (const char *[]){ "fixed_pll" }, | 356 | .parent_names = (const char *[]){ "fixed_pll" }, |
332 | .num_parents = 1, | 357 | .num_parents = 1, |
333 | }, | 358 | }, |
334 | }; | 359 | }; |
335 | 360 | ||
336 | static struct clk_fixed_factor axg_fclk_div5 = { | 361 | static struct clk_regmap axg_fclk_div4 = { |
362 | .data = &(struct clk_regmap_gate_data){ | ||
363 | .offset = HHI_MPLL_CNTL6, | ||
364 | .bit_idx = 29, | ||
365 | }, | ||
366 | .hw.init = &(struct clk_init_data){ | ||
367 | .name = "fclk_div4", | ||
368 | .ops = &clk_regmap_gate_ops, | ||
369 | .parent_names = (const char *[]){ "fclk_div4_div" }, | ||
370 | .num_parents = 1, | ||
371 | }, | ||
372 | }; | ||
373 | |||
374 | static struct clk_fixed_factor axg_fclk_div5_div = { | ||
337 | .mult = 1, | 375 | .mult = 1, |
338 | .div = 5, | 376 | .div = 5, |
339 | .hw.init = &(struct clk_init_data){ | 377 | .hw.init = &(struct clk_init_data){ |
340 | .name = "fclk_div5", | 378 | .name = "fclk_div5_div", |
341 | .ops = &clk_fixed_factor_ops, | 379 | .ops = &clk_fixed_factor_ops, |
342 | .parent_names = (const char *[]){ "fixed_pll" }, | 380 | .parent_names = (const char *[]){ "fixed_pll" }, |
343 | .num_parents = 1, | 381 | .num_parents = 1, |
344 | }, | 382 | }, |
345 | }; | 383 | }; |
346 | 384 | ||
347 | static struct clk_fixed_factor axg_fclk_div7 = { | 385 | static struct clk_regmap axg_fclk_div5 = { |
386 | .data = &(struct clk_regmap_gate_data){ | ||
387 | .offset = HHI_MPLL_CNTL6, | ||
388 | .bit_idx = 30, | ||
389 | }, | ||
390 | .hw.init = &(struct clk_init_data){ | ||
391 | .name = "fclk_div5", | ||
392 | .ops = &clk_regmap_gate_ops, | ||
393 | .parent_names = (const char *[]){ "fclk_div5_div" }, | ||
394 | .num_parents = 1, | ||
395 | }, | ||
396 | }; | ||
397 | |||
398 | static struct clk_fixed_factor axg_fclk_div7_div = { | ||
348 | .mult = 1, | 399 | .mult = 1, |
349 | .div = 7, | 400 | .div = 7, |
350 | .hw.init = &(struct clk_init_data){ | 401 | .hw.init = &(struct clk_init_data){ |
351 | .name = "fclk_div7", | 402 | .name = "fclk_div7_div", |
352 | .ops = &clk_fixed_factor_ops, | 403 | .ops = &clk_fixed_factor_ops, |
353 | .parent_names = (const char *[]){ "fixed_pll" }, | 404 | .parent_names = (const char *[]){ "fixed_pll" }, |
354 | .num_parents = 1, | 405 | .num_parents = 1, |
355 | }, | 406 | }, |
356 | }; | 407 | }; |
357 | 408 | ||
358 | static struct meson_clk_mpll axg_mpll0 = { | 409 | static struct clk_regmap axg_fclk_div7 = { |
359 | .sdm = { | 410 | .data = &(struct clk_regmap_gate_data){ |
360 | .reg_off = HHI_MPLL_CNTL7, | 411 | .offset = HHI_MPLL_CNTL6, |
361 | .shift = 0, | 412 | .bit_idx = 31, |
362 | .width = 14, | ||
363 | }, | 413 | }, |
364 | .sdm_en = { | 414 | .hw.init = &(struct clk_init_data){ |
365 | .reg_off = HHI_MPLL_CNTL7, | 415 | .name = "fclk_div7", |
366 | .shift = 15, | 416 | .ops = &clk_regmap_gate_ops, |
367 | .width = 1, | 417 | .parent_names = (const char *[]){ "fclk_div7_div" }, |
418 | .num_parents = 1, | ||
368 | }, | 419 | }, |
369 | .n2 = { | 420 | }; |
370 | .reg_off = HHI_MPLL_CNTL7, | 421 | |
371 | .shift = 16, | 422 | static struct clk_regmap axg_mpll_prediv = { |
372 | .width = 9, | 423 | .data = &(struct clk_regmap_div_data){ |
424 | .offset = HHI_MPLL_CNTL5, | ||
425 | .shift = 12, | ||
426 | .width = 1, | ||
373 | }, | 427 | }, |
374 | .en = { | 428 | .hw.init = &(struct clk_init_data){ |
375 | .reg_off = HHI_MPLL_CNTL7, | 429 | .name = "mpll_prediv", |
376 | .shift = 14, | 430 | .ops = &clk_regmap_divider_ro_ops, |
377 | .width = 1, | 431 | .parent_names = (const char *[]){ "fixed_pll" }, |
432 | .num_parents = 1, | ||
378 | }, | 433 | }, |
379 | .ssen = { | 434 | }; |
380 | .reg_off = HHI_MPLL_CNTL, | 435 | |
381 | .shift = 25, | 436 | static struct clk_regmap axg_mpll0_div = { |
382 | .width = 1, | 437 | .data = &(struct meson_clk_mpll_data){ |
438 | .sdm = { | ||
439 | .reg_off = HHI_MPLL_CNTL7, | ||
440 | .shift = 0, | ||
441 | .width = 14, | ||
442 | }, | ||
443 | .sdm_en = { | ||
444 | .reg_off = HHI_MPLL_CNTL7, | ||
445 | .shift = 15, | ||
446 | .width = 1, | ||
447 | }, | ||
448 | .n2 = { | ||
449 | .reg_off = HHI_MPLL_CNTL7, | ||
450 | .shift = 16, | ||
451 | .width = 9, | ||
452 | }, | ||
453 | .ssen = { | ||
454 | .reg_off = HHI_MPLL_CNTL, | ||
455 | .shift = 25, | ||
456 | .width = 1, | ||
457 | }, | ||
458 | .misc = { | ||
459 | .reg_off = HHI_PLL_TOP_MISC, | ||
460 | .shift = 0, | ||
461 | .width = 1, | ||
462 | }, | ||
463 | .lock = &meson_clk_lock, | ||
383 | }, | 464 | }, |
384 | .lock = &meson_clk_lock, | ||
385 | .hw.init = &(struct clk_init_data){ | 465 | .hw.init = &(struct clk_init_data){ |
386 | .name = "mpll0", | 466 | .name = "mpll0_div", |
387 | .ops = &meson_clk_mpll_ops, | 467 | .ops = &meson_clk_mpll_ops, |
388 | .parent_names = (const char *[]){ "fixed_pll" }, | 468 | .parent_names = (const char *[]){ "mpll_prediv" }, |
389 | .num_parents = 1, | 469 | .num_parents = 1, |
390 | }, | 470 | }, |
391 | }; | 471 | }; |
392 | 472 | ||
393 | static struct meson_clk_mpll axg_mpll1 = { | 473 | static struct clk_regmap axg_mpll0 = { |
394 | .sdm = { | 474 | .data = &(struct clk_regmap_gate_data){ |
395 | .reg_off = HHI_MPLL_CNTL8, | 475 | .offset = HHI_MPLL_CNTL7, |
396 | .shift = 0, | 476 | .bit_idx = 14, |
397 | .width = 14, | ||
398 | }, | 477 | }, |
399 | .sdm_en = { | 478 | .hw.init = &(struct clk_init_data){ |
400 | .reg_off = HHI_MPLL_CNTL8, | 479 | .name = "mpll0", |
401 | .shift = 15, | 480 | .ops = &clk_regmap_gate_ops, |
402 | .width = 1, | 481 | .parent_names = (const char *[]){ "mpll0_div" }, |
403 | }, | 482 | .num_parents = 1, |
404 | .n2 = { | 483 | .flags = CLK_SET_RATE_PARENT, |
405 | .reg_off = HHI_MPLL_CNTL8, | ||
406 | .shift = 16, | ||
407 | .width = 9, | ||
408 | }, | 484 | }, |
409 | .en = { | 485 | }; |
410 | .reg_off = HHI_MPLL_CNTL8, | 486 | |
411 | .shift = 14, | 487 | static struct clk_regmap axg_mpll1_div = { |
412 | .width = 1, | 488 | .data = &(struct meson_clk_mpll_data){ |
489 | .sdm = { | ||
490 | .reg_off = HHI_MPLL_CNTL8, | ||
491 | .shift = 0, | ||
492 | .width = 14, | ||
493 | }, | ||
494 | .sdm_en = { | ||
495 | .reg_off = HHI_MPLL_CNTL8, | ||
496 | .shift = 15, | ||
497 | .width = 1, | ||
498 | }, | ||
499 | .n2 = { | ||
500 | .reg_off = HHI_MPLL_CNTL8, | ||
501 | .shift = 16, | ||
502 | .width = 9, | ||
503 | }, | ||
504 | .misc = { | ||
505 | .reg_off = HHI_PLL_TOP_MISC, | ||
506 | .shift = 1, | ||
507 | .width = 1, | ||
508 | }, | ||
509 | .lock = &meson_clk_lock, | ||
413 | }, | 510 | }, |
414 | .lock = &meson_clk_lock, | ||
415 | .hw.init = &(struct clk_init_data){ | 511 | .hw.init = &(struct clk_init_data){ |
416 | .name = "mpll1", | 512 | .name = "mpll1_div", |
417 | .ops = &meson_clk_mpll_ops, | 513 | .ops = &meson_clk_mpll_ops, |
418 | .parent_names = (const char *[]){ "fixed_pll" }, | 514 | .parent_names = (const char *[]){ "mpll_prediv" }, |
419 | .num_parents = 1, | 515 | .num_parents = 1, |
420 | }, | 516 | }, |
421 | }; | 517 | }; |
422 | 518 | ||
423 | static struct meson_clk_mpll axg_mpll2 = { | 519 | static struct clk_regmap axg_mpll1 = { |
424 | .sdm = { | 520 | .data = &(struct clk_regmap_gate_data){ |
425 | .reg_off = HHI_MPLL_CNTL9, | 521 | .offset = HHI_MPLL_CNTL8, |
426 | .shift = 0, | 522 | .bit_idx = 14, |
427 | .width = 14, | ||
428 | }, | 523 | }, |
429 | .sdm_en = { | 524 | .hw.init = &(struct clk_init_data){ |
430 | .reg_off = HHI_MPLL_CNTL9, | 525 | .name = "mpll1", |
431 | .shift = 15, | 526 | .ops = &clk_regmap_gate_ops, |
432 | .width = 1, | 527 | .parent_names = (const char *[]){ "mpll1_div" }, |
433 | }, | 528 | .num_parents = 1, |
434 | .n2 = { | 529 | .flags = CLK_SET_RATE_PARENT, |
435 | .reg_off = HHI_MPLL_CNTL9, | ||
436 | .shift = 16, | ||
437 | .width = 9, | ||
438 | }, | 530 | }, |
439 | .en = { | 531 | }; |
440 | .reg_off = HHI_MPLL_CNTL9, | 532 | |
441 | .shift = 14, | 533 | static struct clk_regmap axg_mpll2_div = { |
442 | .width = 1, | 534 | .data = &(struct meson_clk_mpll_data){ |
535 | .sdm = { | ||
536 | .reg_off = HHI_MPLL_CNTL9, | ||
537 | .shift = 0, | ||
538 | .width = 14, | ||
539 | }, | ||
540 | .sdm_en = { | ||
541 | .reg_off = HHI_MPLL_CNTL9, | ||
542 | .shift = 15, | ||
543 | .width = 1, | ||
544 | }, | ||
545 | .n2 = { | ||
546 | .reg_off = HHI_MPLL_CNTL9, | ||
547 | .shift = 16, | ||
548 | .width = 9, | ||
549 | }, | ||
550 | .misc = { | ||
551 | .reg_off = HHI_PLL_TOP_MISC, | ||
552 | .shift = 2, | ||
553 | .width = 1, | ||
554 | }, | ||
555 | .lock = &meson_clk_lock, | ||
443 | }, | 556 | }, |
444 | .lock = &meson_clk_lock, | ||
445 | .hw.init = &(struct clk_init_data){ | 557 | .hw.init = &(struct clk_init_data){ |
446 | .name = "mpll2", | 558 | .name = "mpll2_div", |
447 | .ops = &meson_clk_mpll_ops, | 559 | .ops = &meson_clk_mpll_ops, |
448 | .parent_names = (const char *[]){ "fixed_pll" }, | 560 | .parent_names = (const char *[]){ "mpll_prediv" }, |
449 | .num_parents = 1, | 561 | .num_parents = 1, |
450 | }, | 562 | }, |
451 | }; | 563 | }; |
452 | 564 | ||
453 | static struct meson_clk_mpll axg_mpll3 = { | 565 | static struct clk_regmap axg_mpll2 = { |
454 | .sdm = { | 566 | .data = &(struct clk_regmap_gate_data){ |
455 | .reg_off = HHI_MPLL3_CNTL0, | 567 | .offset = HHI_MPLL_CNTL9, |
456 | .shift = 12, | 568 | .bit_idx = 14, |
457 | .width = 14, | ||
458 | }, | 569 | }, |
459 | .sdm_en = { | 570 | .hw.init = &(struct clk_init_data){ |
460 | .reg_off = HHI_MPLL3_CNTL0, | 571 | .name = "mpll2", |
461 | .shift = 11, | 572 | .ops = &clk_regmap_gate_ops, |
462 | .width = 1, | 573 | .parent_names = (const char *[]){ "mpll2_div" }, |
574 | .num_parents = 1, | ||
575 | .flags = CLK_SET_RATE_PARENT, | ||
576 | }, | ||
577 | }; | ||
578 | |||
579 | static struct clk_regmap axg_mpll3_div = { | ||
580 | .data = &(struct meson_clk_mpll_data){ | ||
581 | .sdm = { | ||
582 | .reg_off = HHI_MPLL3_CNTL0, | ||
583 | .shift = 12, | ||
584 | .width = 14, | ||
585 | }, | ||
586 | .sdm_en = { | ||
587 | .reg_off = HHI_MPLL3_CNTL0, | ||
588 | .shift = 11, | ||
589 | .width = 1, | ||
590 | }, | ||
591 | .n2 = { | ||
592 | .reg_off = HHI_MPLL3_CNTL0, | ||
593 | .shift = 2, | ||
594 | .width = 9, | ||
595 | }, | ||
596 | .misc = { | ||
597 | .reg_off = HHI_PLL_TOP_MISC, | ||
598 | .shift = 3, | ||
599 | .width = 1, | ||
600 | }, | ||
601 | .lock = &meson_clk_lock, | ||
463 | }, | 602 | }, |
464 | .n2 = { | 603 | .hw.init = &(struct clk_init_data){ |
465 | .reg_off = HHI_MPLL3_CNTL0, | 604 | .name = "mpll3_div", |
466 | .shift = 2, | 605 | .ops = &meson_clk_mpll_ops, |
467 | .width = 9, | 606 | .parent_names = (const char *[]){ "mpll_prediv" }, |
607 | .num_parents = 1, | ||
468 | }, | 608 | }, |
469 | .en = { | 609 | }; |
470 | .reg_off = HHI_MPLL3_CNTL0, | 610 | |
471 | .shift = 0, | 611 | static struct clk_regmap axg_mpll3 = { |
472 | .width = 1, | 612 | .data = &(struct clk_regmap_gate_data){ |
613 | .offset = HHI_MPLL3_CNTL0, | ||
614 | .bit_idx = 0, | ||
473 | }, | 615 | }, |
474 | .lock = &meson_clk_lock, | ||
475 | .hw.init = &(struct clk_init_data){ | 616 | .hw.init = &(struct clk_init_data){ |
476 | .name = "mpll3", | 617 | .name = "mpll3", |
477 | .ops = &meson_clk_mpll_ops, | 618 | .ops = &clk_regmap_gate_ops, |
478 | .parent_names = (const char *[]){ "fixed_pll" }, | 619 | .parent_names = (const char *[]){ "mpll3_div" }, |
479 | .num_parents = 1, | 620 | .num_parents = 1, |
621 | .flags = CLK_SET_RATE_PARENT, | ||
480 | }, | 622 | }, |
481 | }; | 623 | }; |
482 | 624 | ||
483 | /* | ||
484 | * FIXME The legacy composite clocks (e.g. clk81) are both PLL post-dividers | ||
485 | * and should be modeled with their respective PLLs via the forthcoming | ||
486 | * coordinated clock rates feature | ||
487 | */ | ||
488 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; | 625 | static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; |
489 | static const char * const clk81_parent_names[] = { | 626 | static const char * const clk81_parent_names[] = { |
490 | "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", | 627 | "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", |
491 | "fclk_div3", "fclk_div5" | 628 | "fclk_div3", "fclk_div5" |
492 | }; | 629 | }; |
493 | 630 | ||
494 | static struct clk_mux axg_mpeg_clk_sel = { | 631 | static struct clk_regmap axg_mpeg_clk_sel = { |
495 | .reg = (void *)HHI_MPEG_CLK_CNTL, | 632 | .data = &(struct clk_regmap_mux_data){ |
496 | .mask = 0x7, | 633 | .offset = HHI_MPEG_CLK_CNTL, |
497 | .shift = 12, | 634 | .mask = 0x7, |
498 | .flags = CLK_MUX_READ_ONLY, | 635 | .shift = 12, |
499 | .table = mux_table_clk81, | 636 | .table = mux_table_clk81, |
500 | .lock = &meson_clk_lock, | 637 | }, |
501 | .hw.init = &(struct clk_init_data){ | 638 | .hw.init = &(struct clk_init_data){ |
502 | .name = "mpeg_clk_sel", | 639 | .name = "mpeg_clk_sel", |
503 | .ops = &clk_mux_ro_ops, | 640 | .ops = &clk_regmap_mux_ro_ops, |
504 | .parent_names = clk81_parent_names, | 641 | .parent_names = clk81_parent_names, |
505 | .num_parents = ARRAY_SIZE(clk81_parent_names), | 642 | .num_parents = ARRAY_SIZE(clk81_parent_names), |
506 | }, | 643 | }, |
507 | }; | 644 | }; |
508 | 645 | ||
509 | static struct clk_divider axg_mpeg_clk_div = { | 646 | static struct clk_regmap axg_mpeg_clk_div = { |
510 | .reg = (void *)HHI_MPEG_CLK_CNTL, | 647 | .data = &(struct clk_regmap_div_data){ |
511 | .shift = 0, | 648 | .offset = HHI_MPEG_CLK_CNTL, |
512 | .width = 7, | 649 | .shift = 0, |
513 | .lock = &meson_clk_lock, | 650 | .width = 7, |
651 | }, | ||
514 | .hw.init = &(struct clk_init_data){ | 652 | .hw.init = &(struct clk_init_data){ |
515 | .name = "mpeg_clk_div", | 653 | .name = "mpeg_clk_div", |
516 | .ops = &clk_divider_ops, | 654 | .ops = &clk_regmap_divider_ops, |
517 | .parent_names = (const char *[]){ "mpeg_clk_sel" }, | 655 | .parent_names = (const char *[]){ "mpeg_clk_sel" }, |
518 | .num_parents = 1, | 656 | .num_parents = 1, |
519 | .flags = CLK_SET_RATE_PARENT, | 657 | .flags = CLK_SET_RATE_PARENT, |
520 | }, | 658 | }, |
521 | }; | 659 | }; |
522 | 660 | ||
523 | static struct clk_gate axg_clk81 = { | 661 | static struct clk_regmap axg_clk81 = { |
524 | .reg = (void *)HHI_MPEG_CLK_CNTL, | 662 | .data = &(struct clk_regmap_gate_data){ |
525 | .bit_idx = 7, | 663 | .offset = HHI_MPEG_CLK_CNTL, |
526 | .lock = &meson_clk_lock, | 664 | .bit_idx = 7, |
665 | }, | ||
527 | .hw.init = &(struct clk_init_data){ | 666 | .hw.init = &(struct clk_init_data){ |
528 | .name = "clk81", | 667 | .name = "clk81", |
529 | .ops = &clk_gate_ops, | 668 | .ops = &clk_regmap_gate_ops, |
530 | .parent_names = (const char *[]){ "mpeg_clk_div" }, | 669 | .parent_names = (const char *[]){ "mpeg_clk_div" }, |
531 | .num_parents = 1, | 670 | .num_parents = 1, |
532 | .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), | 671 | .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), |
@@ -545,42 +684,45 @@ static const char * const axg_sd_emmc_clk0_parent_names[] = { | |||
545 | }; | 684 | }; |
546 | 685 | ||
547 | /* SDcard clock */ | 686 | /* SDcard clock */ |
548 | static struct clk_mux axg_sd_emmc_b_clk0_sel = { | 687 | static struct clk_regmap axg_sd_emmc_b_clk0_sel = { |
549 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | 688 | .data = &(struct clk_regmap_mux_data){ |
550 | .mask = 0x7, | 689 | .offset = HHI_SD_EMMC_CLK_CNTL, |
551 | .shift = 25, | 690 | .mask = 0x7, |
552 | .lock = &meson_clk_lock, | 691 | .shift = 25, |
692 | }, | ||
553 | .hw.init = &(struct clk_init_data) { | 693 | .hw.init = &(struct clk_init_data) { |
554 | .name = "sd_emmc_b_clk0_sel", | 694 | .name = "sd_emmc_b_clk0_sel", |
555 | .ops = &clk_mux_ops, | 695 | .ops = &clk_regmap_mux_ops, |
556 | .parent_names = axg_sd_emmc_clk0_parent_names, | 696 | .parent_names = axg_sd_emmc_clk0_parent_names, |
557 | .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), | 697 | .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), |
558 | .flags = CLK_SET_RATE_PARENT, | 698 | .flags = CLK_SET_RATE_PARENT, |
559 | }, | 699 | }, |
560 | }; | 700 | }; |
561 | 701 | ||
562 | static struct clk_divider axg_sd_emmc_b_clk0_div = { | 702 | static struct clk_regmap axg_sd_emmc_b_clk0_div = { |
563 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | 703 | .data = &(struct clk_regmap_div_data){ |
564 | .shift = 16, | 704 | .offset = HHI_SD_EMMC_CLK_CNTL, |
565 | .width = 7, | 705 | .shift = 16, |
566 | .lock = &meson_clk_lock, | 706 | .width = 7, |
567 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | 707 | .flags = CLK_DIVIDER_ROUND_CLOSEST, |
708 | }, | ||
568 | .hw.init = &(struct clk_init_data) { | 709 | .hw.init = &(struct clk_init_data) { |
569 | .name = "sd_emmc_b_clk0_div", | 710 | .name = "sd_emmc_b_clk0_div", |
570 | .ops = &clk_divider_ops, | 711 | .ops = &clk_regmap_divider_ops, |
571 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, | 712 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" }, |
572 | .num_parents = 1, | 713 | .num_parents = 1, |
573 | .flags = CLK_SET_RATE_PARENT, | 714 | .flags = CLK_SET_RATE_PARENT, |
574 | }, | 715 | }, |
575 | }; | 716 | }; |
576 | 717 | ||
577 | static struct clk_gate axg_sd_emmc_b_clk0 = { | 718 | static struct clk_regmap axg_sd_emmc_b_clk0 = { |
578 | .reg = (void *)HHI_SD_EMMC_CLK_CNTL, | 719 | .data = &(struct clk_regmap_gate_data){ |
579 | .bit_idx = 23, | 720 | .offset = HHI_SD_EMMC_CLK_CNTL, |
580 | .lock = &meson_clk_lock, | 721 | .bit_idx = 23, |
722 | }, | ||
581 | .hw.init = &(struct clk_init_data){ | 723 | .hw.init = &(struct clk_init_data){ |
582 | .name = "sd_emmc_b_clk0", | 724 | .name = "sd_emmc_b_clk0", |
583 | .ops = &clk_gate_ops, | 725 | .ops = &clk_regmap_gate_ops, |
584 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, | 726 | .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" }, |
585 | .num_parents = 1, | 727 | .num_parents = 1, |
586 | .flags = CLK_SET_RATE_PARENT, | 728 | .flags = CLK_SET_RATE_PARENT, |
@@ -588,42 +730,45 @@ static struct clk_gate axg_sd_emmc_b_clk0 = { | |||
588 | }; | 730 | }; |
589 | 731 | ||
590 | /* EMMC/NAND clock */ | 732 | /* EMMC/NAND clock */ |
591 | static struct clk_mux axg_sd_emmc_c_clk0_sel = { | 733 | static struct clk_regmap axg_sd_emmc_c_clk0_sel = { |
592 | .reg = (void *)HHI_NAND_CLK_CNTL, | 734 | .data = &(struct clk_regmap_mux_data){ |
593 | .mask = 0x7, | 735 | .offset = HHI_NAND_CLK_CNTL, |
594 | .shift = 9, | 736 | .mask = 0x7, |
595 | .lock = &meson_clk_lock, | 737 | .shift = 9, |
738 | }, | ||
596 | .hw.init = &(struct clk_init_data) { | 739 | .hw.init = &(struct clk_init_data) { |
597 | .name = "sd_emmc_c_clk0_sel", | 740 | .name = "sd_emmc_c_clk0_sel", |
598 | .ops = &clk_mux_ops, | 741 | .ops = &clk_regmap_mux_ops, |
599 | .parent_names = axg_sd_emmc_clk0_parent_names, | 742 | .parent_names = axg_sd_emmc_clk0_parent_names, |
600 | .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), | 743 | .num_parents = ARRAY_SIZE(axg_sd_emmc_clk0_parent_names), |
601 | .flags = CLK_SET_RATE_PARENT, | 744 | .flags = CLK_SET_RATE_PARENT, |
602 | }, | 745 | }, |
603 | }; | 746 | }; |
604 | 747 | ||
605 | static struct clk_divider axg_sd_emmc_c_clk0_div = { | 748 | static struct clk_regmap axg_sd_emmc_c_clk0_div = { |
606 | .reg = (void *)HHI_NAND_CLK_CNTL, | 749 | .data = &(struct clk_regmap_div_data){ |
607 | .shift = 0, | 750 | .offset = HHI_NAND_CLK_CNTL, |
608 | .width = 7, | 751 | .shift = 0, |
609 | .lock = &meson_clk_lock, | 752 | .width = 7, |
610 | .flags = CLK_DIVIDER_ROUND_CLOSEST, | 753 | .flags = CLK_DIVIDER_ROUND_CLOSEST, |
754 | }, | ||
611 | .hw.init = &(struct clk_init_data) { | 755 | .hw.init = &(struct clk_init_data) { |
612 | .name = "sd_emmc_c_clk0_div", | 756 | .name = "sd_emmc_c_clk0_div", |
613 | .ops = &clk_divider_ops, | 757 | .ops = &clk_regmap_divider_ops, |
614 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, | 758 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" }, |
615 | .num_parents = 1, | 759 | .num_parents = 1, |
616 | .flags = CLK_SET_RATE_PARENT, | 760 | .flags = CLK_SET_RATE_PARENT, |
617 | }, | 761 | }, |
618 | }; | 762 | }; |
619 | 763 | ||
620 | static struct clk_gate axg_sd_emmc_c_clk0 = { | 764 | static struct clk_regmap axg_sd_emmc_c_clk0 = { |
621 | .reg = (void *)HHI_NAND_CLK_CNTL, | 765 | .data = &(struct clk_regmap_gate_data){ |
622 | .bit_idx = 7, | 766 | .offset = HHI_NAND_CLK_CNTL, |
623 | .lock = &meson_clk_lock, | 767 | .bit_idx = 7, |
768 | }, | ||
624 | .hw.init = &(struct clk_init_data){ | 769 | .hw.init = &(struct clk_init_data){ |
625 | .name = "sd_emmc_c_clk0", | 770 | .name = "sd_emmc_c_clk0", |
626 | .ops = &clk_gate_ops, | 771 | .ops = &clk_regmap_gate_ops, |
627 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, | 772 | .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" }, |
628 | .num_parents = 1, | 773 | .num_parents = 1, |
629 | .flags = CLK_SET_RATE_PARENT, | 774 | .flags = CLK_SET_RATE_PARENT, |
@@ -750,27 +895,24 @@ static struct clk_hw_onecell_data axg_hw_onecell_data = { | |||
750 | [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw, | 895 | [CLKID_SD_EMMC_C_CLK0_SEL] = &axg_sd_emmc_c_clk0_sel.hw, |
751 | [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw, | 896 | [CLKID_SD_EMMC_C_CLK0_DIV] = &axg_sd_emmc_c_clk0_div.hw, |
752 | [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw, | 897 | [CLKID_SD_EMMC_C_CLK0] = &axg_sd_emmc_c_clk0.hw, |
898 | [CLKID_MPLL0_DIV] = &axg_mpll0_div.hw, | ||
899 | [CLKID_MPLL1_DIV] = &axg_mpll1_div.hw, | ||
900 | [CLKID_MPLL2_DIV] = &axg_mpll2_div.hw, | ||
901 | [CLKID_MPLL3_DIV] = &axg_mpll3_div.hw, | ||
902 | [CLKID_HIFI_PLL] = &axg_hifi_pll.hw, | ||
903 | [CLKID_MPLL_PREDIV] = &axg_mpll_prediv.hw, | ||
904 | [CLKID_FCLK_DIV2_DIV] = &axg_fclk_div2_div.hw, | ||
905 | [CLKID_FCLK_DIV3_DIV] = &axg_fclk_div3_div.hw, | ||
906 | [CLKID_FCLK_DIV4_DIV] = &axg_fclk_div4_div.hw, | ||
907 | [CLKID_FCLK_DIV5_DIV] = &axg_fclk_div5_div.hw, | ||
908 | [CLKID_FCLK_DIV7_DIV] = &axg_fclk_div7_div.hw, | ||
753 | [NR_CLKS] = NULL, | 909 | [NR_CLKS] = NULL, |
754 | }, | 910 | }, |
755 | .num = NR_CLKS, | 911 | .num = NR_CLKS, |
756 | }; | 912 | }; |
757 | 913 | ||
758 | /* Convenience tables to populate base addresses in .probe */ | 914 | /* Convenience table to populate regmap in .probe */ |
759 | 915 | static struct clk_regmap *const axg_clk_regmaps[] = { | |
760 | static struct meson_clk_pll *const axg_clk_plls[] = { | ||
761 | &axg_fixed_pll, | ||
762 | &axg_sys_pll, | ||
763 | &axg_gp0_pll, | ||
764 | }; | ||
765 | |||
766 | static struct meson_clk_mpll *const axg_clk_mplls[] = { | ||
767 | &axg_mpll0, | ||
768 | &axg_mpll1, | ||
769 | &axg_mpll2, | ||
770 | &axg_mpll3, | ||
771 | }; | ||
772 | |||
773 | static struct clk_gate *const axg_clk_gates[] = { | ||
774 | &axg_clk81, | 916 | &axg_clk81, |
775 | &axg_ddr, | 917 | &axg_ddr, |
776 | &axg_audio_locker, | 918 | &axg_audio_locker, |
@@ -818,113 +960,100 @@ static struct clk_gate *const axg_clk_gates[] = { | |||
818 | &axg_ao_i2c, | 960 | &axg_ao_i2c, |
819 | &axg_sd_emmc_b_clk0, | 961 | &axg_sd_emmc_b_clk0, |
820 | &axg_sd_emmc_c_clk0, | 962 | &axg_sd_emmc_c_clk0, |
821 | }; | ||
822 | |||
823 | static struct clk_mux *const axg_clk_muxes[] = { | ||
824 | &axg_mpeg_clk_sel, | ||
825 | &axg_sd_emmc_b_clk0_sel, | ||
826 | &axg_sd_emmc_c_clk0_sel, | ||
827 | }; | ||
828 | |||
829 | static struct clk_divider *const axg_clk_dividers[] = { | ||
830 | &axg_mpeg_clk_div, | 963 | &axg_mpeg_clk_div, |
831 | &axg_sd_emmc_b_clk0_div, | 964 | &axg_sd_emmc_b_clk0_div, |
832 | &axg_sd_emmc_c_clk0_div, | 965 | &axg_sd_emmc_c_clk0_div, |
833 | }; | 966 | &axg_mpeg_clk_sel, |
834 | 967 | &axg_sd_emmc_b_clk0_sel, | |
835 | struct clkc_data { | 968 | &axg_sd_emmc_c_clk0_sel, |
836 | struct clk_gate *const *clk_gates; | 969 | &axg_mpll0, |
837 | unsigned int clk_gates_count; | 970 | &axg_mpll1, |
838 | struct meson_clk_mpll *const *clk_mplls; | 971 | &axg_mpll2, |
839 | unsigned int clk_mplls_count; | 972 | &axg_mpll3, |
840 | struct meson_clk_pll *const *clk_plls; | 973 | &axg_mpll0_div, |
841 | unsigned int clk_plls_count; | 974 | &axg_mpll1_div, |
842 | struct clk_mux *const *clk_muxes; | 975 | &axg_mpll2_div, |
843 | unsigned int clk_muxes_count; | 976 | &axg_mpll3_div, |
844 | struct clk_divider *const *clk_dividers; | 977 | &axg_fixed_pll, |
845 | unsigned int clk_dividers_count; | 978 | &axg_sys_pll, |
846 | struct clk_hw_onecell_data *hw_onecell_data; | 979 | &axg_gp0_pll, |
847 | }; | 980 | &axg_hifi_pll, |
848 | 981 | &axg_mpll_prediv, | |
849 | static const struct clkc_data axg_clkc_data = { | 982 | &axg_fclk_div2, |
850 | .clk_gates = axg_clk_gates, | 983 | &axg_fclk_div3, |
851 | .clk_gates_count = ARRAY_SIZE(axg_clk_gates), | 984 | &axg_fclk_div4, |
852 | .clk_mplls = axg_clk_mplls, | 985 | &axg_fclk_div5, |
853 | .clk_mplls_count = ARRAY_SIZE(axg_clk_mplls), | 986 | &axg_fclk_div7, |
854 | .clk_plls = axg_clk_plls, | ||
855 | .clk_plls_count = ARRAY_SIZE(axg_clk_plls), | ||
856 | .clk_muxes = axg_clk_muxes, | ||
857 | .clk_muxes_count = ARRAY_SIZE(axg_clk_muxes), | ||
858 | .clk_dividers = axg_clk_dividers, | ||
859 | .clk_dividers_count = ARRAY_SIZE(axg_clk_dividers), | ||
860 | .hw_onecell_data = &axg_hw_onecell_data, | ||
861 | }; | 987 | }; |
862 | 988 | ||
863 | static const struct of_device_id clkc_match_table[] = { | 989 | static const struct of_device_id clkc_match_table[] = { |
864 | { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data }, | 990 | { .compatible = "amlogic,axg-clkc" }, |
865 | {} | 991 | {} |
866 | }; | 992 | }; |
867 | 993 | ||
994 | static const struct regmap_config clkc_regmap_config = { | ||
995 | .reg_bits = 32, | ||
996 | .val_bits = 32, | ||
997 | .reg_stride = 4, | ||
998 | }; | ||
999 | |||
868 | static int axg_clkc_probe(struct platform_device *pdev) | 1000 | static int axg_clkc_probe(struct platform_device *pdev) |
869 | { | 1001 | { |
870 | struct device *dev = &pdev->dev; | 1002 | struct device *dev = &pdev->dev; |
871 | const struct clkc_data *clkc_data; | ||
872 | struct resource *res; | 1003 | struct resource *res; |
873 | void __iomem *clk_base; | 1004 | void __iomem *clk_base = NULL; |
874 | int ret, clkid, i; | 1005 | struct regmap *map; |
875 | 1006 | int ret, i; | |
876 | clkc_data = of_device_get_match_data(&pdev->dev); | ||
877 | if (!clkc_data) | ||
878 | return -EINVAL; | ||
879 | |||
880 | /* Generic clocks and PLLs */ | ||
881 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
882 | if (!res) | ||
883 | return -EINVAL; | ||
884 | clk_base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
885 | if (!clk_base) { | ||
886 | dev_err(&pdev->dev, "Unable to map clk base\n"); | ||
887 | return -ENXIO; | ||
888 | } | ||
889 | 1007 | ||
890 | /* Populate base address for PLLs */ | 1008 | /* Get the hhi system controller node if available */ |
891 | for (i = 0; i < clkc_data->clk_plls_count; i++) | 1009 | map = syscon_node_to_regmap(of_get_parent(dev->of_node)); |
892 | clkc_data->clk_plls[i]->base = clk_base; | 1010 | if (IS_ERR(map)) { |
1011 | dev_err(dev, | ||
1012 | "failed to get HHI regmap - Trying obsolete regs\n"); | ||
893 | 1013 | ||
894 | /* Populate base address for MPLLs */ | 1014 | /* |
895 | for (i = 0; i < clkc_data->clk_mplls_count; i++) | 1015 | * FIXME: HHI registers should be accessed through |
896 | clkc_data->clk_mplls[i]->base = clk_base; | 1016 | * the appropriate system controller. This is required because |
1017 | * there is more than just clocks in this register space | ||
1018 | * | ||
1019 | * This fallback method is only provided temporarily until | ||
1020 | * all the platform DTs are properly using the syscon node | ||
1021 | */ | ||
1022 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
1023 | if (!res) | ||
1024 | return -EINVAL; | ||
897 | 1025 | ||
898 | /* Populate base address for gates */ | ||
899 | for (i = 0; i < clkc_data->clk_gates_count; i++) | ||
900 | clkc_data->clk_gates[i]->reg = clk_base + | ||
901 | (u64)clkc_data->clk_gates[i]->reg; | ||
902 | 1026 | ||
903 | /* Populate base address for muxes */ | 1027 | clk_base = devm_ioremap(dev, res->start, resource_size(res)); |
904 | for (i = 0; i < clkc_data->clk_muxes_count; i++) | 1028 | if (!clk_base) { |
905 | clkc_data->clk_muxes[i]->reg = clk_base + | 1029 | dev_err(dev, "Unable to map clk base\n"); |
906 | (u64)clkc_data->clk_muxes[i]->reg; | 1030 | return -ENXIO; |
1031 | } | ||
1032 | |||
1033 | map = devm_regmap_init_mmio(dev, clk_base, | ||
1034 | &clkc_regmap_config); | ||
1035 | if (IS_ERR(map)) | ||
1036 | return PTR_ERR(map); | ||
1037 | } | ||
907 | 1038 | ||
908 | /* Populate base address for dividers */ | 1039 | /* Populate regmap for the regmap backed clocks */ |
909 | for (i = 0; i < clkc_data->clk_dividers_count; i++) | 1040 | for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++) |
910 | clkc_data->clk_dividers[i]->reg = clk_base + | 1041 | axg_clk_regmaps[i]->map = map; |
911 | (u64)clkc_data->clk_dividers[i]->reg; | ||
912 | 1042 | ||
913 | for (clkid = 0; clkid < clkc_data->hw_onecell_data->num; clkid++) { | 1043 | for (i = 0; i < axg_hw_onecell_data.num; i++) { |
914 | /* array might be sparse */ | 1044 | /* array might be sparse */ |
915 | if (!clkc_data->hw_onecell_data->hws[clkid]) | 1045 | if (!axg_hw_onecell_data.hws[i]) |
916 | continue; | 1046 | continue; |
917 | 1047 | ||
918 | ret = devm_clk_hw_register(dev, | 1048 | ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]); |
919 | clkc_data->hw_onecell_data->hws[clkid]); | ||
920 | if (ret) { | 1049 | if (ret) { |
921 | dev_err(&pdev->dev, "Clock registration failed\n"); | 1050 | dev_err(dev, "Clock registration failed\n"); |
922 | return ret; | 1051 | return ret; |
923 | } | 1052 | } |
924 | } | 1053 | } |
925 | 1054 | ||
926 | return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, | 1055 | return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, |
927 | clkc_data->hw_onecell_data); | 1056 | &axg_hw_onecell_data); |
928 | } | 1057 | } |
929 | 1058 | ||
930 | static struct platform_driver axg_driver = { | 1059 | static struct platform_driver axg_driver = { |