aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/meson/meson8b.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/meson/meson8b.c')
-rw-r--r--drivers/clk/meson/meson8b.c705
1 files changed, 452 insertions, 253 deletions
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 3ffea80c1308..cc2992493e0b 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -23,14 +23,16 @@
23 23
24#include <linux/clk.h> 24#include <linux/clk.h>
25#include <linux/clk-provider.h> 25#include <linux/clk-provider.h>
26#include <linux/init.h>
26#include <linux/of_address.h> 27#include <linux/of_address.h>
27#include <linux/platform_device.h> 28#include <linux/platform_device.h>
28#include <linux/reset-controller.h> 29#include <linux/reset-controller.h>
29#include <linux/slab.h> 30#include <linux/slab.h>
30#include <linux/init.h> 31#include <linux/regmap.h>
31 32
32#include "clkc.h" 33#include "clkc.h"
33#include "meson8b.h" 34#include "meson8b.h"
35#include "clk-regmap.h"
34 36
35static DEFINE_SPINLOCK(meson_clk_lock); 37static DEFINE_SPINLOCK(meson_clk_lock);
36 38
@@ -97,20 +99,6 @@ static const struct pll_rate_table sys_pll_rate_table[] = {
97 { /* sentinel */ }, 99 { /* sentinel */ },
98}; 100};
99 101
100static const struct clk_div_table cpu_div_table[] = {
101 { .val = 1, .div = 1 },
102 { .val = 2, .div = 2 },
103 { .val = 3, .div = 3 },
104 { .val = 2, .div = 4 },
105 { .val = 3, .div = 6 },
106 { .val = 4, .div = 8 },
107 { .val = 5, .div = 10 },
108 { .val = 6, .div = 12 },
109 { .val = 7, .div = 14 },
110 { .val = 8, .div = 16 },
111 { /* sentinel */ },
112};
113
114static struct clk_fixed_rate meson8b_xtal = { 102static struct clk_fixed_rate meson8b_xtal = {
115 .fixed_rate = 24000000, 103 .fixed_rate = 24000000,
116 .hw.init = &(struct clk_init_data){ 104 .hw.init = &(struct clk_init_data){
@@ -120,23 +108,39 @@ static struct clk_fixed_rate meson8b_xtal = {
120 }, 108 },
121}; 109};
122 110
123static struct meson_clk_pll meson8b_fixed_pll = { 111static struct clk_regmap meson8b_fixed_pll = {
124 .m = { 112 .data = &(struct meson_clk_pll_data){
125 .reg_off = HHI_MPLL_CNTL, 113 .m = {
126 .shift = 0, 114 .reg_off = HHI_MPLL_CNTL,
127 .width = 9, 115 .shift = 0,
128 }, 116 .width = 9,
129 .n = { 117 },
130 .reg_off = HHI_MPLL_CNTL, 118 .n = {
131 .shift = 9, 119 .reg_off = HHI_MPLL_CNTL,
132 .width = 5, 120 .shift = 9,
133 }, 121 .width = 5,
134 .od = { 122 },
135 .reg_off = HHI_MPLL_CNTL, 123 .od = {
136 .shift = 16, 124 .reg_off = HHI_MPLL_CNTL,
137 .width = 2, 125 .shift = 16,
126 .width = 2,
127 },
128 .frac = {
129 .reg_off = HHI_MPLL_CNTL2,
130 .shift = 0,
131 .width = 12,
132 },
133 .l = {
134 .reg_off = HHI_MPLL_CNTL,
135 .shift = 31,
136 .width = 1,
137 },
138 .rst = {
139 .reg_off = HHI_MPLL_CNTL,
140 .shift = 29,
141 .width = 1,
142 },
138 }, 143 },
139 .lock = &meson_clk_lock,
140 .hw.init = &(struct clk_init_data){ 144 .hw.init = &(struct clk_init_data){
141 .name = "fixed_pll", 145 .name = "fixed_pll",
142 .ops = &meson_clk_pll_ro_ops, 146 .ops = &meson_clk_pll_ro_ops,
@@ -146,23 +150,34 @@ static struct meson_clk_pll meson8b_fixed_pll = {
146 }, 150 },
147}; 151};
148 152
149static struct meson_clk_pll meson8b_vid_pll = { 153static struct clk_regmap meson8b_vid_pll = {
150 .m = { 154 .data = &(struct meson_clk_pll_data){
151 .reg_off = HHI_VID_PLL_CNTL, 155 .m = {
152 .shift = 0, 156 .reg_off = HHI_VID_PLL_CNTL,
153 .width = 9, 157 .shift = 0,
158 .width = 9,
159 },
160 .n = {
161 .reg_off = HHI_VID_PLL_CNTL,
162 .shift = 9,
163 .width = 5,
164 },
165 .od = {
166 .reg_off = HHI_VID_PLL_CNTL,
167 .shift = 16,
168 .width = 2,
169 },
170 .l = {
171 .reg_off = HHI_VID_PLL_CNTL,
172 .shift = 31,
173 .width = 1,
174 },
175 .rst = {
176 .reg_off = HHI_VID_PLL_CNTL,
177 .shift = 29,
178 .width = 1,
179 },
154 }, 180 },
155 .n = {
156 .reg_off = HHI_VID_PLL_CNTL,
157 .shift = 9,
158 .width = 5,
159 },
160 .od = {
161 .reg_off = HHI_VID_PLL_CNTL,
162 .shift = 16,
163 .width = 2,
164 },
165 .lock = &meson_clk_lock,
166 .hw.init = &(struct clk_init_data){ 181 .hw.init = &(struct clk_init_data){
167 .name = "vid_pll", 182 .name = "vid_pll",
168 .ops = &meson_clk_pll_ro_ops, 183 .ops = &meson_clk_pll_ro_ops,
@@ -172,213 +187,317 @@ static struct meson_clk_pll meson8b_vid_pll = {
172 }, 187 },
173}; 188};
174 189
175static struct meson_clk_pll meson8b_sys_pll = { 190static struct clk_regmap meson8b_sys_pll = {
176 .m = { 191 .data = &(struct meson_clk_pll_data){
177 .reg_off = HHI_SYS_PLL_CNTL, 192 .m = {
178 .shift = 0, 193 .reg_off = HHI_SYS_PLL_CNTL,
179 .width = 9, 194 .shift = 0,
180 }, 195 .width = 9,
181 .n = { 196 },
182 .reg_off = HHI_SYS_PLL_CNTL, 197 .n = {
183 .shift = 9, 198 .reg_off = HHI_SYS_PLL_CNTL,
184 .width = 5, 199 .shift = 9,
200 .width = 5,
201 },
202 .od = {
203 .reg_off = HHI_SYS_PLL_CNTL,
204 .shift = 16,
205 .width = 2,
206 },
207 .l = {
208 .reg_off = HHI_SYS_PLL_CNTL,
209 .shift = 31,
210 .width = 1,
211 },
212 .rst = {
213 .reg_off = HHI_SYS_PLL_CNTL,
214 .shift = 29,
215 .width = 1,
216 },
217 .table = sys_pll_rate_table,
185 }, 218 },
186 .od = {
187 .reg_off = HHI_SYS_PLL_CNTL,
188 .shift = 16,
189 .width = 2,
190 },
191 .rate_table = sys_pll_rate_table,
192 .rate_count = ARRAY_SIZE(sys_pll_rate_table),
193 .lock = &meson_clk_lock,
194 .hw.init = &(struct clk_init_data){ 219 .hw.init = &(struct clk_init_data){
195 .name = "sys_pll", 220 .name = "sys_pll",
196 .ops = &meson_clk_pll_ops, 221 .ops = &meson_clk_pll_ro_ops,
197 .parent_names = (const char *[]){ "xtal" }, 222 .parent_names = (const char *[]){ "xtal" },
198 .num_parents = 1, 223 .num_parents = 1,
199 .flags = CLK_GET_RATE_NOCACHE, 224 .flags = CLK_GET_RATE_NOCACHE,
200 }, 225 },
201}; 226};
202 227
203static struct clk_fixed_factor meson8b_fclk_div2 = { 228static struct clk_fixed_factor meson8b_fclk_div2_div = {
204 .mult = 1, 229 .mult = 1,
205 .div = 2, 230 .div = 2,
206 .hw.init = &(struct clk_init_data){ 231 .hw.init = &(struct clk_init_data){
207 .name = "fclk_div2", 232 .name = "fclk_div2_div",
208 .ops = &clk_fixed_factor_ops, 233 .ops = &clk_fixed_factor_ops,
209 .parent_names = (const char *[]){ "fixed_pll" }, 234 .parent_names = (const char *[]){ "fixed_pll" },
210 .num_parents = 1, 235 .num_parents = 1,
211 }, 236 },
212}; 237};
213 238
214static struct clk_fixed_factor meson8b_fclk_div3 = { 239static struct clk_regmap meson8b_fclk_div2 = {
240 .data = &(struct clk_regmap_gate_data){
241 .offset = HHI_MPLL_CNTL6,
242 .bit_idx = 27,
243 },
244 .hw.init = &(struct clk_init_data){
245 .name = "fclk_div2",
246 .ops = &clk_regmap_gate_ops,
247 .parent_names = (const char *[]){ "fclk_div2_div" },
248 .num_parents = 1,
249 },
250};
251
252static struct clk_fixed_factor meson8b_fclk_div3_div = {
215 .mult = 1, 253 .mult = 1,
216 .div = 3, 254 .div = 3,
217 .hw.init = &(struct clk_init_data){ 255 .hw.init = &(struct clk_init_data){
218 .name = "fclk_div3", 256 .name = "fclk_div_div3",
219 .ops = &clk_fixed_factor_ops, 257 .ops = &clk_fixed_factor_ops,
220 .parent_names = (const char *[]){ "fixed_pll" }, 258 .parent_names = (const char *[]){ "fixed_pll" },
221 .num_parents = 1, 259 .num_parents = 1,
222 }, 260 },
223}; 261};
224 262
225static struct clk_fixed_factor meson8b_fclk_div4 = { 263static struct clk_regmap meson8b_fclk_div3 = {
264 .data = &(struct clk_regmap_gate_data){
265 .offset = HHI_MPLL_CNTL6,
266 .bit_idx = 28,
267 },
268 .hw.init = &(struct clk_init_data){
269 .name = "fclk_div3",
270 .ops = &clk_regmap_gate_ops,
271 .parent_names = (const char *[]){ "fclk_div3_div" },
272 .num_parents = 1,
273 },
274};
275
276static struct clk_fixed_factor meson8b_fclk_div4_div = {
226 .mult = 1, 277 .mult = 1,
227 .div = 4, 278 .div = 4,
228 .hw.init = &(struct clk_init_data){ 279 .hw.init = &(struct clk_init_data){
229 .name = "fclk_div4", 280 .name = "fclk_div4_div",
230 .ops = &clk_fixed_factor_ops, 281 .ops = &clk_fixed_factor_ops,
231 .parent_names = (const char *[]){ "fixed_pll" }, 282 .parent_names = (const char *[]){ "fixed_pll" },
232 .num_parents = 1, 283 .num_parents = 1,
233 }, 284 },
234}; 285};
235 286
236static struct clk_fixed_factor meson8b_fclk_div5 = { 287static struct clk_regmap meson8b_fclk_div4 = {
288 .data = &(struct clk_regmap_gate_data){
289 .offset = HHI_MPLL_CNTL6,
290 .bit_idx = 29,
291 },
292 .hw.init = &(struct clk_init_data){
293 .name = "fclk_div4",
294 .ops = &clk_regmap_gate_ops,
295 .parent_names = (const char *[]){ "fclk_div4_div" },
296 .num_parents = 1,
297 },
298};
299
300static struct clk_fixed_factor meson8b_fclk_div5_div = {
237 .mult = 1, 301 .mult = 1,
238 .div = 5, 302 .div = 5,
239 .hw.init = &(struct clk_init_data){ 303 .hw.init = &(struct clk_init_data){
240 .name = "fclk_div5", 304 .name = "fclk_div5_div",
241 .ops = &clk_fixed_factor_ops, 305 .ops = &clk_fixed_factor_ops,
242 .parent_names = (const char *[]){ "fixed_pll" }, 306 .parent_names = (const char *[]){ "fixed_pll" },
243 .num_parents = 1, 307 .num_parents = 1,
244 }, 308 },
245}; 309};
246 310
247static struct clk_fixed_factor meson8b_fclk_div7 = { 311static struct clk_regmap meson8b_fclk_div5 = {
312 .data = &(struct clk_regmap_gate_data){
313 .offset = HHI_MPLL_CNTL6,
314 .bit_idx = 30,
315 },
316 .hw.init = &(struct clk_init_data){
317 .name = "fclk_div5",
318 .ops = &clk_regmap_gate_ops,
319 .parent_names = (const char *[]){ "fclk_div5_div" },
320 .num_parents = 1,
321 },
322};
323
324static struct clk_fixed_factor meson8b_fclk_div7_div = {
248 .mult = 1, 325 .mult = 1,
249 .div = 7, 326 .div = 7,
250 .hw.init = &(struct clk_init_data){ 327 .hw.init = &(struct clk_init_data){
251 .name = "fclk_div7", 328 .name = "fclk_div7_div",
252 .ops = &clk_fixed_factor_ops, 329 .ops = &clk_fixed_factor_ops,
253 .parent_names = (const char *[]){ "fixed_pll" }, 330 .parent_names = (const char *[]){ "fixed_pll" },
254 .num_parents = 1, 331 .num_parents = 1,
255 }, 332 },
256}; 333};
257 334
258static struct meson_clk_mpll meson8b_mpll0 = { 335static struct clk_regmap meson8b_fclk_div7 = {
259 .sdm = { 336 .data = &(struct clk_regmap_gate_data){
260 .reg_off = HHI_MPLL_CNTL7, 337 .offset = HHI_MPLL_CNTL6,
261 .shift = 0, 338 .bit_idx = 31,
262 .width = 14,
263 }, 339 },
264 .sdm_en = { 340 .hw.init = &(struct clk_init_data){
265 .reg_off = HHI_MPLL_CNTL7, 341 .name = "fclk_div7",
266 .shift = 15, 342 .ops = &clk_regmap_gate_ops,
267 .width = 1, 343 .parent_names = (const char *[]){ "fclk_div7_div" },
344 .num_parents = 1,
268 }, 345 },
269 .n2 = { 346};
270 .reg_off = HHI_MPLL_CNTL7, 347
271 .shift = 16, 348static struct clk_regmap meson8b_mpll_prediv = {
272 .width = 9, 349 .data = &(struct clk_regmap_div_data){
350 .offset = HHI_MPLL_CNTL5,
351 .shift = 12,
352 .width = 1,
273 }, 353 },
274 .en = { 354 .hw.init = &(struct clk_init_data){
275 .reg_off = HHI_MPLL_CNTL7, 355 .name = "mpll_prediv",
276 .shift = 14, 356 .ops = &clk_regmap_divider_ro_ops,
277 .width = 1, 357 .parent_names = (const char *[]){ "fixed_pll" },
358 .num_parents = 1,
278 }, 359 },
279 .ssen = { 360};
280 .reg_off = HHI_MPLL_CNTL, 361
281 .shift = 25, 362static struct clk_regmap meson8b_mpll0_div = {
282 .width = 1, 363 .data = &(struct meson_clk_mpll_data){
364 .sdm = {
365 .reg_off = HHI_MPLL_CNTL7,
366 .shift = 0,
367 .width = 14,
368 },
369 .sdm_en = {
370 .reg_off = HHI_MPLL_CNTL7,
371 .shift = 15,
372 .width = 1,
373 },
374 .n2 = {
375 .reg_off = HHI_MPLL_CNTL7,
376 .shift = 16,
377 .width = 9,
378 },
379 .ssen = {
380 .reg_off = HHI_MPLL_CNTL,
381 .shift = 25,
382 .width = 1,
383 },
384 .lock = &meson_clk_lock,
283 }, 385 },
284 .lock = &meson_clk_lock,
285 .hw.init = &(struct clk_init_data){ 386 .hw.init = &(struct clk_init_data){
286 .name = "mpll0", 387 .name = "mpll0_div",
287 .ops = &meson_clk_mpll_ops, 388 .ops = &meson_clk_mpll_ops,
288 .parent_names = (const char *[]){ "fixed_pll" }, 389 .parent_names = (const char *[]){ "mpll_prediv" },
289 .num_parents = 1, 390 .num_parents = 1,
290 }, 391 },
291}; 392};
292 393
293static struct meson_clk_mpll meson8b_mpll1 = { 394static struct clk_regmap meson8b_mpll0 = {
294 .sdm = { 395 .data = &(struct clk_regmap_gate_data){
295 .reg_off = HHI_MPLL_CNTL8, 396 .offset = HHI_MPLL_CNTL7,
296 .shift = 0, 397 .bit_idx = 14,
297 .width = 14,
298 }, 398 },
299 .sdm_en = { 399 .hw.init = &(struct clk_init_data){
300 .reg_off = HHI_MPLL_CNTL8, 400 .name = "mpll0",
301 .shift = 15, 401 .ops = &clk_regmap_gate_ops,
302 .width = 1, 402 .parent_names = (const char *[]){ "mpll0_div" },
303 }, 403 .num_parents = 1,
304 .n2 = { 404 .flags = CLK_SET_RATE_PARENT,
305 .reg_off = HHI_MPLL_CNTL8,
306 .shift = 16,
307 .width = 9,
308 }, 405 },
309 .en = { 406};
310 .reg_off = HHI_MPLL_CNTL8, 407
311 .shift = 14, 408static struct clk_regmap meson8b_mpll1_div = {
312 .width = 1, 409 .data = &(struct meson_clk_mpll_data){
410 .sdm = {
411 .reg_off = HHI_MPLL_CNTL8,
412 .shift = 0,
413 .width = 14,
414 },
415 .sdm_en = {
416 .reg_off = HHI_MPLL_CNTL8,
417 .shift = 15,
418 .width = 1,
419 },
420 .n2 = {
421 .reg_off = HHI_MPLL_CNTL8,
422 .shift = 16,
423 .width = 9,
424 },
425 .lock = &meson_clk_lock,
313 }, 426 },
314 .lock = &meson_clk_lock,
315 .hw.init = &(struct clk_init_data){ 427 .hw.init = &(struct clk_init_data){
316 .name = "mpll1", 428 .name = "mpll1_div",
317 .ops = &meson_clk_mpll_ops, 429 .ops = &meson_clk_mpll_ops,
318 .parent_names = (const char *[]){ "fixed_pll" }, 430 .parent_names = (const char *[]){ "mpll_prediv" },
319 .num_parents = 1, 431 .num_parents = 1,
320 }, 432 },
321}; 433};
322 434
323static struct meson_clk_mpll meson8b_mpll2 = { 435static struct clk_regmap meson8b_mpll1 = {
324 .sdm = { 436 .data = &(struct clk_regmap_gate_data){
325 .reg_off = HHI_MPLL_CNTL9, 437 .offset = HHI_MPLL_CNTL8,
326 .shift = 0, 438 .bit_idx = 14,
327 .width = 14,
328 },
329 .sdm_en = {
330 .reg_off = HHI_MPLL_CNTL9,
331 .shift = 15,
332 .width = 1,
333 }, 439 },
334 .n2 = { 440 .hw.init = &(struct clk_init_data){
335 .reg_off = HHI_MPLL_CNTL9, 441 .name = "mpll1",
336 .shift = 16, 442 .ops = &clk_regmap_gate_ops,
337 .width = 9, 443 .parent_names = (const char *[]){ "mpll1_div" },
444 .num_parents = 1,
445 .flags = CLK_SET_RATE_PARENT,
338 }, 446 },
339 .en = { 447};
340 .reg_off = HHI_MPLL_CNTL9, 448
341 .shift = 14, 449static struct clk_regmap meson8b_mpll2_div = {
342 .width = 1, 450 .data = &(struct meson_clk_mpll_data){
451 .sdm = {
452 .reg_off = HHI_MPLL_CNTL9,
453 .shift = 0,
454 .width = 14,
455 },
456 .sdm_en = {
457 .reg_off = HHI_MPLL_CNTL9,
458 .shift = 15,
459 .width = 1,
460 },
461 .n2 = {
462 .reg_off = HHI_MPLL_CNTL9,
463 .shift = 16,
464 .width = 9,
465 },
466 .lock = &meson_clk_lock,
343 }, 467 },
344 .lock = &meson_clk_lock,
345 .hw.init = &(struct clk_init_data){ 468 .hw.init = &(struct clk_init_data){
346 .name = "mpll2", 469 .name = "mpll2_div",
347 .ops = &meson_clk_mpll_ops, 470 .ops = &meson_clk_mpll_ops,
348 .parent_names = (const char *[]){ "fixed_pll" }, 471 .parent_names = (const char *[]){ "mpll_prediv" },
349 .num_parents = 1, 472 .num_parents = 1,
350 }, 473 },
351}; 474};
352 475
353/* 476static struct clk_regmap meson8b_mpll2 = {
354 * FIXME cpu clocks and the legacy composite clocks (e.g. clk81) are both PLL 477 .data = &(struct clk_regmap_gate_data){
355 * post-dividers and should be modeled with their respective PLLs via the 478 .offset = HHI_MPLL_CNTL9,
356 * forthcoming coordinated clock rates feature 479 .bit_idx = 14,
357 */ 480 },
358static struct meson_clk_cpu meson8b_cpu_clk = {
359 .reg_off = HHI_SYS_CPU_CLK_CNTL1,
360 .div_table = cpu_div_table,
361 .clk_nb.notifier_call = meson_clk_cpu_notifier_cb,
362 .hw.init = &(struct clk_init_data){ 481 .hw.init = &(struct clk_init_data){
363 .name = "cpu_clk", 482 .name = "mpll2",
364 .ops = &meson_clk_cpu_ops, 483 .ops = &clk_regmap_gate_ops,
365 .parent_names = (const char *[]){ "sys_pll" }, 484 .parent_names = (const char *[]){ "mpll2_div" },
366 .num_parents = 1, 485 .num_parents = 1,
486 .flags = CLK_SET_RATE_PARENT,
367 }, 487 },
368}; 488};
369 489
370static u32 mux_table_clk81[] = { 6, 5, 7 }; 490static u32 mux_table_clk81[] = { 6, 5, 7 };
371 491static struct clk_regmap meson8b_mpeg_clk_sel = {
372struct clk_mux meson8b_mpeg_clk_sel = { 492 .data = &(struct clk_regmap_mux_data){
373 .reg = (void *)HHI_MPEG_CLK_CNTL, 493 .offset = HHI_MPEG_CLK_CNTL,
374 .mask = 0x7, 494 .mask = 0x7,
375 .shift = 12, 495 .shift = 12,
376 .flags = CLK_MUX_READ_ONLY, 496 .table = mux_table_clk81,
377 .table = mux_table_clk81, 497 },
378 .lock = &meson_clk_lock,
379 .hw.init = &(struct clk_init_data){ 498 .hw.init = &(struct clk_init_data){
380 .name = "mpeg_clk_sel", 499 .name = "mpeg_clk_sel",
381 .ops = &clk_mux_ro_ops, 500 .ops = &clk_regmap_mux_ro_ops,
382 /* 501 /*
383 * FIXME bits 14:12 selects from 8 possible parents: 502 * FIXME bits 14:12 selects from 8 possible parents:
384 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2, 503 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
@@ -387,34 +506,136 @@ struct clk_mux meson8b_mpeg_clk_sel = {
387 .parent_names = (const char *[]){ "fclk_div3", "fclk_div4", 506 .parent_names = (const char *[]){ "fclk_div3", "fclk_div4",
388 "fclk_div5" }, 507 "fclk_div5" },
389 .num_parents = 3, 508 .num_parents = 3,
390 .flags = (CLK_SET_RATE_NO_REPARENT | CLK_IGNORE_UNUSED),
391 }, 509 },
392}; 510};
393 511
394struct clk_divider meson8b_mpeg_clk_div = { 512static struct clk_regmap meson8b_mpeg_clk_div = {
395 .reg = (void *)HHI_MPEG_CLK_CNTL, 513 .data = &(struct clk_regmap_div_data){
396 .shift = 0, 514 .offset = HHI_MPEG_CLK_CNTL,
397 .width = 7, 515 .shift = 0,
398 .lock = &meson_clk_lock, 516 .width = 7,
517 },
399 .hw.init = &(struct clk_init_data){ 518 .hw.init = &(struct clk_init_data){
400 .name = "mpeg_clk_div", 519 .name = "mpeg_clk_div",
401 .ops = &clk_divider_ops, 520 .ops = &clk_regmap_divider_ro_ops,
402 .parent_names = (const char *[]){ "mpeg_clk_sel" }, 521 .parent_names = (const char *[]){ "mpeg_clk_sel" },
403 .num_parents = 1, 522 .num_parents = 1,
404 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),
405 }, 523 },
406}; 524};
407 525
408struct clk_gate meson8b_clk81 = { 526static struct clk_regmap meson8b_clk81 = {
409 .reg = (void *)HHI_MPEG_CLK_CNTL, 527 .data = &(struct clk_regmap_gate_data){
410 .bit_idx = 7, 528 .offset = HHI_MPEG_CLK_CNTL,
411 .lock = &meson_clk_lock, 529 .bit_idx = 7,
530 },
412 .hw.init = &(struct clk_init_data){ 531 .hw.init = &(struct clk_init_data){
413 .name = "clk81", 532 .name = "clk81",
414 .ops = &clk_gate_ops, 533 .ops = &clk_regmap_gate_ops,
415 .parent_names = (const char *[]){ "mpeg_clk_div" }, 534 .parent_names = (const char *[]){ "mpeg_clk_div" },
416 .num_parents = 1, 535 .num_parents = 1,
417 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL), 536 .flags = CLK_IS_CRITICAL,
537 },
538};
539
540static struct clk_regmap meson8b_cpu_in_sel = {
541 .data = &(struct clk_regmap_mux_data){
542 .offset = HHI_SYS_CPU_CLK_CNTL0,
543 .mask = 0x1,
544 .shift = 0,
545 },
546 .hw.init = &(struct clk_init_data){
547 .name = "cpu_in_sel",
548 .ops = &clk_regmap_mux_ro_ops,
549 .parent_names = (const char *[]){ "xtal", "sys_pll" },
550 .num_parents = 2,
551 .flags = (CLK_SET_RATE_PARENT |
552 CLK_SET_RATE_NO_REPARENT),
553 },
554};
555
556static struct clk_fixed_factor meson8b_cpu_div2 = {
557 .mult = 1,
558 .div = 2,
559 .hw.init = &(struct clk_init_data){
560 .name = "cpu_div2",
561 .ops = &clk_fixed_factor_ops,
562 .parent_names = (const char *[]){ "cpu_in_sel" },
563 .num_parents = 1,
564 .flags = CLK_SET_RATE_PARENT,
565 },
566};
567
568static struct clk_fixed_factor meson8b_cpu_div3 = {
569 .mult = 1,
570 .div = 3,
571 .hw.init = &(struct clk_init_data){
572 .name = "cpu_div3",
573 .ops = &clk_fixed_factor_ops,
574 .parent_names = (const char *[]){ "cpu_in_sel" },
575 .num_parents = 1,
576 .flags = CLK_SET_RATE_PARENT,
577 },
578};
579
580static const struct clk_div_table cpu_scale_table[] = {
581 { .val = 2, .div = 4 },
582 { .val = 3, .div = 6 },
583 { .val = 4, .div = 8 },
584 { .val = 5, .div = 10 },
585 { .val = 6, .div = 12 },
586 { .val = 7, .div = 14 },
587 { .val = 8, .div = 16 },
588 { /* sentinel */ },
589};
590
591static struct clk_regmap meson8b_cpu_scale_div = {
592 .data = &(struct clk_regmap_div_data){
593 .offset = HHI_SYS_CPU_CLK_CNTL1,
594 .shift = 20,
595 .width = 9,
596 .table = cpu_scale_table,
597 .flags = CLK_DIVIDER_ALLOW_ZERO,
598 },
599 .hw.init = &(struct clk_init_data){
600 .name = "cpu_scale_div",
601 .ops = &clk_regmap_divider_ro_ops,
602 .parent_names = (const char *[]){ "cpu_in_sel" },
603 .num_parents = 1,
604 .flags = CLK_SET_RATE_PARENT,
605 },
606};
607
608static struct clk_regmap meson8b_cpu_scale_out_sel = {
609 .data = &(struct clk_regmap_mux_data){
610 .offset = HHI_SYS_CPU_CLK_CNTL0,
611 .mask = 0x3,
612 .shift = 2,
613 },
614 .hw.init = &(struct clk_init_data){
615 .name = "cpu_scale_out_sel",
616 .ops = &clk_regmap_mux_ro_ops,
617 .parent_names = (const char *[]) { "cpu_in_sel",
618 "cpu_div2",
619 "cpu_div3",
620 "cpu_scale_div" },
621 .num_parents = 4,
622 .flags = CLK_SET_RATE_PARENT,
623 },
624};
625
626static struct clk_regmap meson8b_cpu_clk = {
627 .data = &(struct clk_regmap_mux_data){
628 .offset = HHI_SYS_CPU_CLK_CNTL0,
629 .mask = 0x1,
630 .shift = 7,
631 },
632 .hw.init = &(struct clk_init_data){
633 .name = "cpu_clk",
634 .ops = &clk_regmap_mux_ro_ops,
635 .parent_names = (const char *[]){ "xtal", "cpu_out_sel" },
636 .num_parents = 2,
637 .flags = (CLK_SET_RATE_PARENT |
638 CLK_SET_RATE_NO_REPARENT),
418 }, 639 },
419}; 640};
420 641
@@ -599,24 +820,26 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
599 [CLKID_MPLL0] = &meson8b_mpll0.hw, 820 [CLKID_MPLL0] = &meson8b_mpll0.hw,
600 [CLKID_MPLL1] = &meson8b_mpll1.hw, 821 [CLKID_MPLL1] = &meson8b_mpll1.hw,
601 [CLKID_MPLL2] = &meson8b_mpll2.hw, 822 [CLKID_MPLL2] = &meson8b_mpll2.hw,
823 [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw,
824 [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw,
825 [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw,
826 [CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw,
827 [CLKID_CPU_DIV2] = &meson8b_cpu_div2.hw,
828 [CLKID_CPU_DIV3] = &meson8b_cpu_div3.hw,
829 [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw,
830 [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw,
831 [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw,
832 [CLKID_FCLK_DIV2_DIV] = &meson8b_fclk_div2_div.hw,
833 [CLKID_FCLK_DIV3_DIV] = &meson8b_fclk_div3_div.hw,
834 [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw,
835 [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw,
836 [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw,
602 [CLK_NR_CLKS] = NULL, 837 [CLK_NR_CLKS] = NULL,
603 }, 838 },
604 .num = CLK_NR_CLKS, 839 .num = CLK_NR_CLKS,
605}; 840};
606 841
607static struct meson_clk_pll *const meson8b_clk_plls[] = { 842static struct clk_regmap *const meson8b_clk_regmaps[] = {
608 &meson8b_fixed_pll,
609 &meson8b_vid_pll,
610 &meson8b_sys_pll,
611};
612
613static struct meson_clk_mpll *const meson8b_clk_mplls[] = {
614 &meson8b_mpll0,
615 &meson8b_mpll1,
616 &meson8b_mpll2,
617};
618
619static struct clk_gate *const meson8b_clk_gates[] = {
620 &meson8b_clk81, 843 &meson8b_clk81,
621 &meson8b_ddr, 844 &meson8b_ddr,
622 &meson8b_dos, 845 &meson8b_dos,
@@ -695,14 +918,27 @@ static struct clk_gate *const meson8b_clk_gates[] = {
695 &meson8b_ao_ahb_sram, 918 &meson8b_ao_ahb_sram,
696 &meson8b_ao_ahb_bus, 919 &meson8b_ao_ahb_bus,
697 &meson8b_ao_iface, 920 &meson8b_ao_iface,
698};
699
700static struct clk_mux *const meson8b_clk_muxes[] = {
701 &meson8b_mpeg_clk_sel,
702};
703
704static struct clk_divider *const meson8b_clk_dividers[] = {
705 &meson8b_mpeg_clk_div, 921 &meson8b_mpeg_clk_div,
922 &meson8b_mpeg_clk_sel,
923 &meson8b_mpll0,
924 &meson8b_mpll1,
925 &meson8b_mpll2,
926 &meson8b_mpll0_div,
927 &meson8b_mpll1_div,
928 &meson8b_mpll2_div,
929 &meson8b_fixed_pll,
930 &meson8b_vid_pll,
931 &meson8b_sys_pll,
932 &meson8b_cpu_in_sel,
933 &meson8b_cpu_scale_div,
934 &meson8b_cpu_scale_out_sel,
935 &meson8b_cpu_clk,
936 &meson8b_mpll_prediv,
937 &meson8b_fclk_div2,
938 &meson8b_fclk_div3,
939 &meson8b_fclk_div4,
940 &meson8b_fclk_div5,
941 &meson8b_fclk_div7,
706}; 942};
707 943
708static const struct meson8b_clk_reset_line { 944static const struct meson8b_clk_reset_line {
@@ -804,82 +1040,45 @@ static const struct reset_control_ops meson8b_clk_reset_ops = {
804 .deassert = meson8b_clk_reset_deassert, 1040 .deassert = meson8b_clk_reset_deassert,
805}; 1041};
806 1042
1043static const struct regmap_config clkc_regmap_config = {
1044 .reg_bits = 32,
1045 .val_bits = 32,
1046 .reg_stride = 4,
1047};
1048
807static int meson8b_clkc_probe(struct platform_device *pdev) 1049static int meson8b_clkc_probe(struct platform_device *pdev)
808{ 1050{
809 int ret, clkid, i; 1051 int ret, i;
810 struct clk_hw *parent_hw;
811 struct clk *parent_clk;
812 struct device *dev = &pdev->dev; 1052 struct device *dev = &pdev->dev;
1053 struct regmap *map;
813 1054
814 if (!clk_base) 1055 if (!clk_base)
815 return -ENXIO; 1056 return -ENXIO;
816 1057
817 /* Populate base address for PLLs */ 1058 map = devm_regmap_init_mmio(dev, clk_base, &clkc_regmap_config);
818 for (i = 0; i < ARRAY_SIZE(meson8b_clk_plls); i++) 1059 if (IS_ERR(map))
819 meson8b_clk_plls[i]->base = clk_base; 1060 return PTR_ERR(map);
820
821 /* Populate base address for MPLLs */
822 for (i = 0; i < ARRAY_SIZE(meson8b_clk_mplls); i++)
823 meson8b_clk_mplls[i]->base = clk_base;
824
825 /* Populate the base address for CPU clk */
826 meson8b_cpu_clk.base = clk_base;
827
828 /* Populate base address for gates */
829 for (i = 0; i < ARRAY_SIZE(meson8b_clk_gates); i++)
830 meson8b_clk_gates[i]->reg = clk_base +
831 (u32)meson8b_clk_gates[i]->reg;
832
833 /* Populate base address for muxes */
834 for (i = 0; i < ARRAY_SIZE(meson8b_clk_muxes); i++)
835 meson8b_clk_muxes[i]->reg = clk_base +
836 (u32)meson8b_clk_muxes[i]->reg;
837 1061
838 /* Populate base address for dividers */ 1062 /* Populate regmap for the regmap backed clocks */
839 for (i = 0; i < ARRAY_SIZE(meson8b_clk_dividers); i++) 1063 for (i = 0; i < ARRAY_SIZE(meson8b_clk_regmaps); i++)
840 meson8b_clk_dividers[i]->reg = clk_base + 1064 meson8b_clk_regmaps[i]->map = map;
841 (u32)meson8b_clk_dividers[i]->reg;
842 1065
843 /* 1066 /*
844 * register all clks 1067 * register all clks
845 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1 1068 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
846 */ 1069 */
847 for (clkid = CLKID_XTAL; clkid < CLK_NR_CLKS; clkid++) { 1070 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
848 /* array might be sparse */ 1071 /* array might be sparse */
849 if (!meson8b_hw_onecell_data.hws[clkid]) 1072 if (!meson8b_hw_onecell_data.hws[i])
850 continue; 1073 continue;
851 1074
852 /* FIXME convert to devm_clk_register */ 1075 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[i]);
853 ret = devm_clk_hw_register(dev, meson8b_hw_onecell_data.hws[clkid]);
854 if (ret) 1076 if (ret)
855 return ret; 1077 return ret;
856 } 1078 }
857 1079
858 /* 1080 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
859 * Register CPU clk notifier 1081 &meson8b_hw_onecell_data);
860 *
861 * FIXME this is wrong for a lot of reasons. First, the muxes should be
862 * struct clk_hw objects. Second, we shouldn't program the muxes in
863 * notifier handlers. The tricky programming sequence will be handled
864 * by the forthcoming coordinated clock rates mechanism once that
865 * feature is released.
866 *
867 * Furthermore, looking up the parent this way is terrible. At some
868 * point we will stop allocating a default struct clk when registering
869 * a new clk_hw, and this hack will no longer work. Releasing the ccr
870 * feature before that time solves the problem :-)
871 */
872 parent_hw = clk_hw_get_parent(&meson8b_cpu_clk.hw);
873 parent_clk = parent_hw->clk;
874 ret = clk_notifier_register(parent_clk, &meson8b_cpu_clk.clk_nb);
875 if (ret) {
876 pr_err("%s: failed to register clock notifier for cpu_clk\n",
877 __func__);
878 return ret;
879 }
880
881 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
882 &meson8b_hw_onecell_data);
883} 1082}
884 1083
885static const struct of_device_id meson8b_clkc_match_table[] = { 1084static const struct of_device_id meson8b_clkc_match_table[] = {