1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2015 Endless Mobile, Inc.
4 * Author: Carlo Caione <carlo@endlessm.com>
6 * Copyright (c) 2016 BayLibre, Inc.
7 * Michael Turquette <mturquette@baylibre.com>
10 #include <linux/clk.h>
11 #include <linux/clk-provider.h>
12 #include <linux/init.h>
13 #include <linux/of_address.h>
14 #include <linux/platform_device.h>
15 #include <linux/reset-controller.h>
16 #include <linux/slab.h>
17 #include <linux/regmap.h>
21 #include "clk-regmap.h"
23 static DEFINE_SPINLOCK(meson_clk_lock
);
25 static void __iomem
*clk_base
;
27 struct meson8b_clk_reset
{
28 struct reset_controller_dev reset
;
32 static const struct pll_rate_table sys_pll_rate_table
[] = {
33 PLL_RATE(312000000, 52, 1, 2),
34 PLL_RATE(336000000, 56, 1, 2),
35 PLL_RATE(360000000, 60, 1, 2),
36 PLL_RATE(384000000, 64, 1, 2),
37 PLL_RATE(408000000, 68, 1, 2),
38 PLL_RATE(432000000, 72, 1, 2),
39 PLL_RATE(456000000, 76, 1, 2),
40 PLL_RATE(480000000, 80, 1, 2),
41 PLL_RATE(504000000, 84, 1, 2),
42 PLL_RATE(528000000, 88, 1, 2),
43 PLL_RATE(552000000, 92, 1, 2),
44 PLL_RATE(576000000, 96, 1, 2),
45 PLL_RATE(600000000, 50, 1, 1),
46 PLL_RATE(624000000, 52, 1, 1),
47 PLL_RATE(648000000, 54, 1, 1),
48 PLL_RATE(672000000, 56, 1, 1),
49 PLL_RATE(696000000, 58, 1, 1),
50 PLL_RATE(720000000, 60, 1, 1),
51 PLL_RATE(744000000, 62, 1, 1),
52 PLL_RATE(768000000, 64, 1, 1),
53 PLL_RATE(792000000, 66, 1, 1),
54 PLL_RATE(816000000, 68, 1, 1),
55 PLL_RATE(840000000, 70, 1, 1),
56 PLL_RATE(864000000, 72, 1, 1),
57 PLL_RATE(888000000, 74, 1, 1),
58 PLL_RATE(912000000, 76, 1, 1),
59 PLL_RATE(936000000, 78, 1, 1),
60 PLL_RATE(960000000, 80, 1, 1),
61 PLL_RATE(984000000, 82, 1, 1),
62 PLL_RATE(1008000000, 84, 1, 1),
63 PLL_RATE(1032000000, 86, 1, 1),
64 PLL_RATE(1056000000, 88, 1, 1),
65 PLL_RATE(1080000000, 90, 1, 1),
66 PLL_RATE(1104000000, 92, 1, 1),
67 PLL_RATE(1128000000, 94, 1, 1),
68 PLL_RATE(1152000000, 96, 1, 1),
69 PLL_RATE(1176000000, 98, 1, 1),
70 PLL_RATE(1200000000, 50, 1, 0),
71 PLL_RATE(1224000000, 51, 1, 0),
72 PLL_RATE(1248000000, 52, 1, 0),
73 PLL_RATE(1272000000, 53, 1, 0),
74 PLL_RATE(1296000000, 54, 1, 0),
75 PLL_RATE(1320000000, 55, 1, 0),
76 PLL_RATE(1344000000, 56, 1, 0),
77 PLL_RATE(1368000000, 57, 1, 0),
78 PLL_RATE(1392000000, 58, 1, 0),
79 PLL_RATE(1416000000, 59, 1, 0),
80 PLL_RATE(1440000000, 60, 1, 0),
81 PLL_RATE(1464000000, 61, 1, 0),
82 PLL_RATE(1488000000, 62, 1, 0),
83 PLL_RATE(1512000000, 63, 1, 0),
84 PLL_RATE(1536000000, 64, 1, 0),
88 static struct clk_fixed_rate meson8b_xtal
= {
89 .fixed_rate
= 24000000,
90 .hw
.init
= &(struct clk_init_data
){
93 .ops
= &clk_fixed_rate_ops
,
97 static struct clk_regmap meson8b_fixed_pll
= {
98 .data
= &(struct meson_clk_pll_data
){
100 .reg_off
= HHI_MPLL_CNTL
,
105 .reg_off
= HHI_MPLL_CNTL
,
110 .reg_off
= HHI_MPLL_CNTL
,
115 .reg_off
= HHI_MPLL_CNTL2
,
120 .reg_off
= HHI_MPLL_CNTL
,
125 .reg_off
= HHI_MPLL_CNTL
,
130 .hw
.init
= &(struct clk_init_data
){
132 .ops
= &meson_clk_pll_ro_ops
,
133 .parent_names
= (const char *[]){ "xtal" },
135 .flags
= CLK_GET_RATE_NOCACHE
,
139 static struct clk_regmap meson8b_vid_pll
= {
140 .data
= &(struct meson_clk_pll_data
){
142 .reg_off
= HHI_VID_PLL_CNTL
,
147 .reg_off
= HHI_VID_PLL_CNTL
,
152 .reg_off
= HHI_VID_PLL_CNTL
,
157 .reg_off
= HHI_VID_PLL_CNTL
,
162 .reg_off
= HHI_VID_PLL_CNTL
,
167 .hw
.init
= &(struct clk_init_data
){
169 .ops
= &meson_clk_pll_ro_ops
,
170 .parent_names
= (const char *[]){ "xtal" },
172 .flags
= CLK_GET_RATE_NOCACHE
,
176 static struct clk_regmap meson8b_sys_pll
= {
177 .data
= &(struct meson_clk_pll_data
){
179 .reg_off
= HHI_SYS_PLL_CNTL
,
184 .reg_off
= HHI_SYS_PLL_CNTL
,
189 .reg_off
= HHI_SYS_PLL_CNTL
,
194 .reg_off
= HHI_SYS_PLL_CNTL
,
199 .reg_off
= HHI_SYS_PLL_CNTL
,
203 .table
= sys_pll_rate_table
,
205 .hw
.init
= &(struct clk_init_data
){
207 .ops
= &meson_clk_pll_ro_ops
,
208 .parent_names
= (const char *[]){ "xtal" },
210 .flags
= CLK_GET_RATE_NOCACHE
,
214 static struct clk_fixed_factor meson8b_fclk_div2_div
= {
217 .hw
.init
= &(struct clk_init_data
){
218 .name
= "fclk_div2_div",
219 .ops
= &clk_fixed_factor_ops
,
220 .parent_names
= (const char *[]){ "fixed_pll" },
225 static struct clk_regmap meson8b_fclk_div2
= {
226 .data
= &(struct clk_regmap_gate_data
){
227 .offset
= HHI_MPLL_CNTL6
,
230 .hw
.init
= &(struct clk_init_data
){
232 .ops
= &clk_regmap_gate_ops
,
233 .parent_names
= (const char *[]){ "fclk_div2_div" },
236 * FIXME: Ethernet with a RGMII PHYs is not working if
237 * fclk_div2 is disabled. it is currently unclear why this
238 * is. keep it enabled until the Ethernet driver knows how
239 * to manage this clock.
241 .flags
= CLK_IS_CRITICAL
,
245 static struct clk_fixed_factor meson8b_fclk_div3_div
= {
248 .hw
.init
= &(struct clk_init_data
){
249 .name
= "fclk_div3_div",
250 .ops
= &clk_fixed_factor_ops
,
251 .parent_names
= (const char *[]){ "fixed_pll" },
256 static struct clk_regmap meson8b_fclk_div3
= {
257 .data
= &(struct clk_regmap_gate_data
){
258 .offset
= HHI_MPLL_CNTL6
,
261 .hw
.init
= &(struct clk_init_data
){
263 .ops
= &clk_regmap_gate_ops
,
264 .parent_names
= (const char *[]){ "fclk_div3_div" },
269 static struct clk_fixed_factor meson8b_fclk_div4_div
= {
272 .hw
.init
= &(struct clk_init_data
){
273 .name
= "fclk_div4_div",
274 .ops
= &clk_fixed_factor_ops
,
275 .parent_names
= (const char *[]){ "fixed_pll" },
280 static struct clk_regmap meson8b_fclk_div4
= {
281 .data
= &(struct clk_regmap_gate_data
){
282 .offset
= HHI_MPLL_CNTL6
,
285 .hw
.init
= &(struct clk_init_data
){
287 .ops
= &clk_regmap_gate_ops
,
288 .parent_names
= (const char *[]){ "fclk_div4_div" },
293 static struct clk_fixed_factor meson8b_fclk_div5_div
= {
296 .hw
.init
= &(struct clk_init_data
){
297 .name
= "fclk_div5_div",
298 .ops
= &clk_fixed_factor_ops
,
299 .parent_names
= (const char *[]){ "fixed_pll" },
304 static struct clk_regmap meson8b_fclk_div5
= {
305 .data
= &(struct clk_regmap_gate_data
){
306 .offset
= HHI_MPLL_CNTL6
,
309 .hw
.init
= &(struct clk_init_data
){
311 .ops
= &clk_regmap_gate_ops
,
312 .parent_names
= (const char *[]){ "fclk_div5_div" },
317 static struct clk_fixed_factor meson8b_fclk_div7_div
= {
320 .hw
.init
= &(struct clk_init_data
){
321 .name
= "fclk_div7_div",
322 .ops
= &clk_fixed_factor_ops
,
323 .parent_names
= (const char *[]){ "fixed_pll" },
328 static struct clk_regmap meson8b_fclk_div7
= {
329 .data
= &(struct clk_regmap_gate_data
){
330 .offset
= HHI_MPLL_CNTL6
,
333 .hw
.init
= &(struct clk_init_data
){
335 .ops
= &clk_regmap_gate_ops
,
336 .parent_names
= (const char *[]){ "fclk_div7_div" },
341 static struct clk_regmap meson8b_mpll_prediv
= {
342 .data
= &(struct clk_regmap_div_data
){
343 .offset
= HHI_MPLL_CNTL5
,
347 .hw
.init
= &(struct clk_init_data
){
348 .name
= "mpll_prediv",
349 .ops
= &clk_regmap_divider_ro_ops
,
350 .parent_names
= (const char *[]){ "fixed_pll" },
355 static struct clk_regmap meson8b_mpll0_div
= {
356 .data
= &(struct meson_clk_mpll_data
){
358 .reg_off
= HHI_MPLL_CNTL7
,
363 .reg_off
= HHI_MPLL_CNTL7
,
368 .reg_off
= HHI_MPLL_CNTL7
,
373 .reg_off
= HHI_MPLL_CNTL
,
377 .lock
= &meson_clk_lock
,
379 .hw
.init
= &(struct clk_init_data
){
381 .ops
= &meson_clk_mpll_ops
,
382 .parent_names
= (const char *[]){ "mpll_prediv" },
387 static struct clk_regmap meson8b_mpll0
= {
388 .data
= &(struct clk_regmap_gate_data
){
389 .offset
= HHI_MPLL_CNTL7
,
392 .hw
.init
= &(struct clk_init_data
){
394 .ops
= &clk_regmap_gate_ops
,
395 .parent_names
= (const char *[]){ "mpll0_div" },
397 .flags
= CLK_SET_RATE_PARENT
,
401 static struct clk_regmap meson8b_mpll1_div
= {
402 .data
= &(struct meson_clk_mpll_data
){
404 .reg_off
= HHI_MPLL_CNTL8
,
409 .reg_off
= HHI_MPLL_CNTL8
,
414 .reg_off
= HHI_MPLL_CNTL8
,
418 .lock
= &meson_clk_lock
,
420 .hw
.init
= &(struct clk_init_data
){
422 .ops
= &meson_clk_mpll_ops
,
423 .parent_names
= (const char *[]){ "mpll_prediv" },
428 static struct clk_regmap meson8b_mpll1
= {
429 .data
= &(struct clk_regmap_gate_data
){
430 .offset
= HHI_MPLL_CNTL8
,
433 .hw
.init
= &(struct clk_init_data
){
435 .ops
= &clk_regmap_gate_ops
,
436 .parent_names
= (const char *[]){ "mpll1_div" },
438 .flags
= CLK_SET_RATE_PARENT
,
442 static struct clk_regmap meson8b_mpll2_div
= {
443 .data
= &(struct meson_clk_mpll_data
){
445 .reg_off
= HHI_MPLL_CNTL9
,
450 .reg_off
= HHI_MPLL_CNTL9
,
455 .reg_off
= HHI_MPLL_CNTL9
,
459 .lock
= &meson_clk_lock
,
461 .hw
.init
= &(struct clk_init_data
){
463 .ops
= &meson_clk_mpll_ops
,
464 .parent_names
= (const char *[]){ "mpll_prediv" },
469 static struct clk_regmap meson8b_mpll2
= {
470 .data
= &(struct clk_regmap_gate_data
){
471 .offset
= HHI_MPLL_CNTL9
,
474 .hw
.init
= &(struct clk_init_data
){
476 .ops
= &clk_regmap_gate_ops
,
477 .parent_names
= (const char *[]){ "mpll2_div" },
479 .flags
= CLK_SET_RATE_PARENT
,
483 static u32 mux_table_clk81
[] = { 6, 5, 7 };
484 static struct clk_regmap meson8b_mpeg_clk_sel
= {
485 .data
= &(struct clk_regmap_mux_data
){
486 .offset
= HHI_MPEG_CLK_CNTL
,
489 .table
= mux_table_clk81
,
491 .hw
.init
= &(struct clk_init_data
){
492 .name
= "mpeg_clk_sel",
493 .ops
= &clk_regmap_mux_ro_ops
,
495 * FIXME bits 14:12 selects from 8 possible parents:
496 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
497 * fclk_div4, fclk_div3, fclk_div5
499 .parent_names
= (const char *[]){ "fclk_div3", "fclk_div4",
505 static struct clk_regmap meson8b_mpeg_clk_div
= {
506 .data
= &(struct clk_regmap_div_data
){
507 .offset
= HHI_MPEG_CLK_CNTL
,
511 .hw
.init
= &(struct clk_init_data
){
512 .name
= "mpeg_clk_div",
513 .ops
= &clk_regmap_divider_ro_ops
,
514 .parent_names
= (const char *[]){ "mpeg_clk_sel" },
519 static struct clk_regmap meson8b_clk81
= {
520 .data
= &(struct clk_regmap_gate_data
){
521 .offset
= HHI_MPEG_CLK_CNTL
,
524 .hw
.init
= &(struct clk_init_data
){
526 .ops
= &clk_regmap_gate_ops
,
527 .parent_names
= (const char *[]){ "mpeg_clk_div" },
529 .flags
= CLK_IS_CRITICAL
,
533 static struct clk_regmap meson8b_cpu_in_sel
= {
534 .data
= &(struct clk_regmap_mux_data
){
535 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
539 .hw
.init
= &(struct clk_init_data
){
540 .name
= "cpu_in_sel",
541 .ops
= &clk_regmap_mux_ro_ops
,
542 .parent_names
= (const char *[]){ "xtal", "sys_pll" },
544 .flags
= (CLK_SET_RATE_PARENT
|
545 CLK_SET_RATE_NO_REPARENT
),
549 static struct clk_fixed_factor meson8b_cpu_div2
= {
552 .hw
.init
= &(struct clk_init_data
){
554 .ops
= &clk_fixed_factor_ops
,
555 .parent_names
= (const char *[]){ "cpu_in_sel" },
557 .flags
= CLK_SET_RATE_PARENT
,
561 static struct clk_fixed_factor meson8b_cpu_div3
= {
564 .hw
.init
= &(struct clk_init_data
){
566 .ops
= &clk_fixed_factor_ops
,
567 .parent_names
= (const char *[]){ "cpu_in_sel" },
569 .flags
= CLK_SET_RATE_PARENT
,
573 static const struct clk_div_table cpu_scale_table
[] = {
574 { .val
= 2, .div
= 4 },
575 { .val
= 3, .div
= 6 },
576 { .val
= 4, .div
= 8 },
577 { .val
= 5, .div
= 10 },
578 { .val
= 6, .div
= 12 },
579 { .val
= 7, .div
= 14 },
580 { .val
= 8, .div
= 16 },
584 static struct clk_regmap meson8b_cpu_scale_div
= {
585 .data
= &(struct clk_regmap_div_data
){
586 .offset
= HHI_SYS_CPU_CLK_CNTL1
,
589 .table
= cpu_scale_table
,
590 .flags
= CLK_DIVIDER_ALLOW_ZERO
,
592 .hw
.init
= &(struct clk_init_data
){
593 .name
= "cpu_scale_div",
594 .ops
= &clk_regmap_divider_ro_ops
,
595 .parent_names
= (const char *[]){ "cpu_in_sel" },
597 .flags
= CLK_SET_RATE_PARENT
,
601 static struct clk_regmap meson8b_cpu_scale_out_sel
= {
602 .data
= &(struct clk_regmap_mux_data
){
603 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
607 .hw
.init
= &(struct clk_init_data
){
608 .name
= "cpu_scale_out_sel",
609 .ops
= &clk_regmap_mux_ro_ops
,
610 .parent_names
= (const char *[]) { "cpu_in_sel",
615 .flags
= CLK_SET_RATE_PARENT
,
619 static struct clk_regmap meson8b_cpu_clk
= {
620 .data
= &(struct clk_regmap_mux_data
){
621 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
625 .hw
.init
= &(struct clk_init_data
){
627 .ops
= &clk_regmap_mux_ro_ops
,
628 .parent_names
= (const char *[]){ "xtal",
629 "cpu_scale_out_sel" },
631 .flags
= (CLK_SET_RATE_PARENT
|
632 CLK_SET_RATE_NO_REPARENT
),
636 static struct clk_regmap meson8b_nand_clk_sel
= {
637 .data
= &(struct clk_regmap_mux_data
){
638 .offset
= HHI_NAND_CLK_CNTL
,
641 .flags
= CLK_MUX_ROUND_CLOSEST
,
643 .hw
.init
= &(struct clk_init_data
){
644 .name
= "nand_clk_sel",
645 .ops
= &clk_regmap_mux_ops
,
646 /* FIXME all other parents are unknown: */
647 .parent_names
= (const char *[]){ "fclk_div4", "fclk_div3",
648 "fclk_div5", "fclk_div7", "xtal" },
650 .flags
= CLK_SET_RATE_PARENT
,
654 static struct clk_regmap meson8b_nand_clk_div
= {
655 .data
= &(struct clk_regmap_div_data
){
656 .offset
= HHI_NAND_CLK_CNTL
,
659 .flags
= CLK_DIVIDER_ROUND_CLOSEST
,
661 .hw
.init
= &(struct clk_init_data
){
662 .name
= "nand_clk_div",
663 .ops
= &clk_regmap_divider_ops
,
664 .parent_names
= (const char *[]){ "nand_clk_sel" },
666 .flags
= CLK_SET_RATE_PARENT
,
670 static struct clk_regmap meson8b_nand_clk_gate
= {
671 .data
= &(struct clk_regmap_gate_data
){
672 .offset
= HHI_NAND_CLK_CNTL
,
675 .hw
.init
= &(struct clk_init_data
){
676 .name
= "nand_clk_gate",
677 .ops
= &clk_regmap_gate_ops
,
678 .parent_names
= (const char *[]){ "nand_clk_div" },
680 .flags
= CLK_SET_RATE_PARENT
,
684 /* Everything Else (EE) domain gates */
686 static MESON_GATE(meson8b_ddr
, HHI_GCLK_MPEG0
, 0);
687 static MESON_GATE(meson8b_dos
, HHI_GCLK_MPEG0
, 1);
688 static MESON_GATE(meson8b_isa
, HHI_GCLK_MPEG0
, 5);
689 static MESON_GATE(meson8b_pl301
, HHI_GCLK_MPEG0
, 6);
690 static MESON_GATE(meson8b_periphs
, HHI_GCLK_MPEG0
, 7);
691 static MESON_GATE(meson8b_spicc
, HHI_GCLK_MPEG0
, 8);
692 static MESON_GATE(meson8b_i2c
, HHI_GCLK_MPEG0
, 9);
693 static MESON_GATE(meson8b_sar_adc
, HHI_GCLK_MPEG0
, 10);
694 static MESON_GATE(meson8b_smart_card
, HHI_GCLK_MPEG0
, 11);
695 static MESON_GATE(meson8b_rng0
, HHI_GCLK_MPEG0
, 12);
696 static MESON_GATE(meson8b_uart0
, HHI_GCLK_MPEG0
, 13);
697 static MESON_GATE(meson8b_sdhc
, HHI_GCLK_MPEG0
, 14);
698 static MESON_GATE(meson8b_stream
, HHI_GCLK_MPEG0
, 15);
699 static MESON_GATE(meson8b_async_fifo
, HHI_GCLK_MPEG0
, 16);
700 static MESON_GATE(meson8b_sdio
, HHI_GCLK_MPEG0
, 17);
701 static MESON_GATE(meson8b_abuf
, HHI_GCLK_MPEG0
, 18);
702 static MESON_GATE(meson8b_hiu_iface
, HHI_GCLK_MPEG0
, 19);
703 static MESON_GATE(meson8b_assist_misc
, HHI_GCLK_MPEG0
, 23);
704 static MESON_GATE(meson8b_spi
, HHI_GCLK_MPEG0
, 30);
706 static MESON_GATE(meson8b_i2s_spdif
, HHI_GCLK_MPEG1
, 2);
707 static MESON_GATE(meson8b_eth
, HHI_GCLK_MPEG1
, 3);
708 static MESON_GATE(meson8b_demux
, HHI_GCLK_MPEG1
, 4);
709 static MESON_GATE(meson8b_aiu_glue
, HHI_GCLK_MPEG1
, 6);
710 static MESON_GATE(meson8b_iec958
, HHI_GCLK_MPEG1
, 7);
711 static MESON_GATE(meson8b_i2s_out
, HHI_GCLK_MPEG1
, 8);
712 static MESON_GATE(meson8b_amclk
, HHI_GCLK_MPEG1
, 9);
713 static MESON_GATE(meson8b_aififo2
, HHI_GCLK_MPEG1
, 10);
714 static MESON_GATE(meson8b_mixer
, HHI_GCLK_MPEG1
, 11);
715 static MESON_GATE(meson8b_mixer_iface
, HHI_GCLK_MPEG1
, 12);
716 static MESON_GATE(meson8b_adc
, HHI_GCLK_MPEG1
, 13);
717 static MESON_GATE(meson8b_blkmv
, HHI_GCLK_MPEG1
, 14);
718 static MESON_GATE(meson8b_aiu
, HHI_GCLK_MPEG1
, 15);
719 static MESON_GATE(meson8b_uart1
, HHI_GCLK_MPEG1
, 16);
720 static MESON_GATE(meson8b_g2d
, HHI_GCLK_MPEG1
, 20);
721 static MESON_GATE(meson8b_usb0
, HHI_GCLK_MPEG1
, 21);
722 static MESON_GATE(meson8b_usb1
, HHI_GCLK_MPEG1
, 22);
723 static MESON_GATE(meson8b_reset
, HHI_GCLK_MPEG1
, 23);
724 static MESON_GATE(meson8b_nand
, HHI_GCLK_MPEG1
, 24);
725 static MESON_GATE(meson8b_dos_parser
, HHI_GCLK_MPEG1
, 25);
726 static MESON_GATE(meson8b_usb
, HHI_GCLK_MPEG1
, 26);
727 static MESON_GATE(meson8b_vdin1
, HHI_GCLK_MPEG1
, 28);
728 static MESON_GATE(meson8b_ahb_arb0
, HHI_GCLK_MPEG1
, 29);
729 static MESON_GATE(meson8b_efuse
, HHI_GCLK_MPEG1
, 30);
730 static MESON_GATE(meson8b_boot_rom
, HHI_GCLK_MPEG1
, 31);
732 static MESON_GATE(meson8b_ahb_data_bus
, HHI_GCLK_MPEG2
, 1);
733 static MESON_GATE(meson8b_ahb_ctrl_bus
, HHI_GCLK_MPEG2
, 2);
734 static MESON_GATE(meson8b_hdmi_intr_sync
, HHI_GCLK_MPEG2
, 3);
735 static MESON_GATE(meson8b_hdmi_pclk
, HHI_GCLK_MPEG2
, 4);
736 static MESON_GATE(meson8b_usb1_ddr_bridge
, HHI_GCLK_MPEG2
, 8);
737 static MESON_GATE(meson8b_usb0_ddr_bridge
, HHI_GCLK_MPEG2
, 9);
738 static MESON_GATE(meson8b_mmc_pclk
, HHI_GCLK_MPEG2
, 11);
739 static MESON_GATE(meson8b_dvin
, HHI_GCLK_MPEG2
, 12);
740 static MESON_GATE(meson8b_uart2
, HHI_GCLK_MPEG2
, 15);
741 static MESON_GATE(meson8b_sana
, HHI_GCLK_MPEG2
, 22);
742 static MESON_GATE(meson8b_vpu_intr
, HHI_GCLK_MPEG2
, 25);
743 static MESON_GATE(meson8b_sec_ahb_ahb3_bridge
, HHI_GCLK_MPEG2
, 26);
744 static MESON_GATE(meson8b_clk81_a9
, HHI_GCLK_MPEG2
, 29);
746 static MESON_GATE(meson8b_vclk2_venci0
, HHI_GCLK_OTHER
, 1);
747 static MESON_GATE(meson8b_vclk2_venci1
, HHI_GCLK_OTHER
, 2);
748 static MESON_GATE(meson8b_vclk2_vencp0
, HHI_GCLK_OTHER
, 3);
749 static MESON_GATE(meson8b_vclk2_vencp1
, HHI_GCLK_OTHER
, 4);
750 static MESON_GATE(meson8b_gclk_venci_int
, HHI_GCLK_OTHER
, 8);
751 static MESON_GATE(meson8b_gclk_vencp_int
, HHI_GCLK_OTHER
, 9);
752 static MESON_GATE(meson8b_dac_clk
, HHI_GCLK_OTHER
, 10);
753 static MESON_GATE(meson8b_aoclk_gate
, HHI_GCLK_OTHER
, 14);
754 static MESON_GATE(meson8b_iec958_gate
, HHI_GCLK_OTHER
, 16);
755 static MESON_GATE(meson8b_enc480p
, HHI_GCLK_OTHER
, 20);
756 static MESON_GATE(meson8b_rng1
, HHI_GCLK_OTHER
, 21);
757 static MESON_GATE(meson8b_gclk_vencl_int
, HHI_GCLK_OTHER
, 22);
758 static MESON_GATE(meson8b_vclk2_venclmcc
, HHI_GCLK_OTHER
, 24);
759 static MESON_GATE(meson8b_vclk2_vencl
, HHI_GCLK_OTHER
, 25);
760 static MESON_GATE(meson8b_vclk2_other
, HHI_GCLK_OTHER
, 26);
761 static MESON_GATE(meson8b_edp
, HHI_GCLK_OTHER
, 31);
763 /* Always On (AO) domain gates */
765 static MESON_GATE(meson8b_ao_media_cpu
, HHI_GCLK_AO
, 0);
766 static MESON_GATE(meson8b_ao_ahb_sram
, HHI_GCLK_AO
, 1);
767 static MESON_GATE(meson8b_ao_ahb_bus
, HHI_GCLK_AO
, 2);
768 static MESON_GATE(meson8b_ao_iface
, HHI_GCLK_AO
, 3);
770 static struct clk_hw_onecell_data meson8b_hw_onecell_data
= {
772 [CLKID_XTAL
] = &meson8b_xtal
.hw
,
773 [CLKID_PLL_FIXED
] = &meson8b_fixed_pll
.hw
,
774 [CLKID_PLL_VID
] = &meson8b_vid_pll
.hw
,
775 [CLKID_PLL_SYS
] = &meson8b_sys_pll
.hw
,
776 [CLKID_FCLK_DIV2
] = &meson8b_fclk_div2
.hw
,
777 [CLKID_FCLK_DIV3
] = &meson8b_fclk_div3
.hw
,
778 [CLKID_FCLK_DIV4
] = &meson8b_fclk_div4
.hw
,
779 [CLKID_FCLK_DIV5
] = &meson8b_fclk_div5
.hw
,
780 [CLKID_FCLK_DIV7
] = &meson8b_fclk_div7
.hw
,
781 [CLKID_CPUCLK
] = &meson8b_cpu_clk
.hw
,
782 [CLKID_MPEG_SEL
] = &meson8b_mpeg_clk_sel
.hw
,
783 [CLKID_MPEG_DIV
] = &meson8b_mpeg_clk_div
.hw
,
784 [CLKID_CLK81
] = &meson8b_clk81
.hw
,
785 [CLKID_DDR
] = &meson8b_ddr
.hw
,
786 [CLKID_DOS
] = &meson8b_dos
.hw
,
787 [CLKID_ISA
] = &meson8b_isa
.hw
,
788 [CLKID_PL301
] = &meson8b_pl301
.hw
,
789 [CLKID_PERIPHS
] = &meson8b_periphs
.hw
,
790 [CLKID_SPICC
] = &meson8b_spicc
.hw
,
791 [CLKID_I2C
] = &meson8b_i2c
.hw
,
792 [CLKID_SAR_ADC
] = &meson8b_sar_adc
.hw
,
793 [CLKID_SMART_CARD
] = &meson8b_smart_card
.hw
,
794 [CLKID_RNG0
] = &meson8b_rng0
.hw
,
795 [CLKID_UART0
] = &meson8b_uart0
.hw
,
796 [CLKID_SDHC
] = &meson8b_sdhc
.hw
,
797 [CLKID_STREAM
] = &meson8b_stream
.hw
,
798 [CLKID_ASYNC_FIFO
] = &meson8b_async_fifo
.hw
,
799 [CLKID_SDIO
] = &meson8b_sdio
.hw
,
800 [CLKID_ABUF
] = &meson8b_abuf
.hw
,
801 [CLKID_HIU_IFACE
] = &meson8b_hiu_iface
.hw
,
802 [CLKID_ASSIST_MISC
] = &meson8b_assist_misc
.hw
,
803 [CLKID_SPI
] = &meson8b_spi
.hw
,
804 [CLKID_I2S_SPDIF
] = &meson8b_i2s_spdif
.hw
,
805 [CLKID_ETH
] = &meson8b_eth
.hw
,
806 [CLKID_DEMUX
] = &meson8b_demux
.hw
,
807 [CLKID_AIU_GLUE
] = &meson8b_aiu_glue
.hw
,
808 [CLKID_IEC958
] = &meson8b_iec958
.hw
,
809 [CLKID_I2S_OUT
] = &meson8b_i2s_out
.hw
,
810 [CLKID_AMCLK
] = &meson8b_amclk
.hw
,
811 [CLKID_AIFIFO2
] = &meson8b_aififo2
.hw
,
812 [CLKID_MIXER
] = &meson8b_mixer
.hw
,
813 [CLKID_MIXER_IFACE
] = &meson8b_mixer_iface
.hw
,
814 [CLKID_ADC
] = &meson8b_adc
.hw
,
815 [CLKID_BLKMV
] = &meson8b_blkmv
.hw
,
816 [CLKID_AIU
] = &meson8b_aiu
.hw
,
817 [CLKID_UART1
] = &meson8b_uart1
.hw
,
818 [CLKID_G2D
] = &meson8b_g2d
.hw
,
819 [CLKID_USB0
] = &meson8b_usb0
.hw
,
820 [CLKID_USB1
] = &meson8b_usb1
.hw
,
821 [CLKID_RESET
] = &meson8b_reset
.hw
,
822 [CLKID_NAND
] = &meson8b_nand
.hw
,
823 [CLKID_DOS_PARSER
] = &meson8b_dos_parser
.hw
,
824 [CLKID_USB
] = &meson8b_usb
.hw
,
825 [CLKID_VDIN1
] = &meson8b_vdin1
.hw
,
826 [CLKID_AHB_ARB0
] = &meson8b_ahb_arb0
.hw
,
827 [CLKID_EFUSE
] = &meson8b_efuse
.hw
,
828 [CLKID_BOOT_ROM
] = &meson8b_boot_rom
.hw
,
829 [CLKID_AHB_DATA_BUS
] = &meson8b_ahb_data_bus
.hw
,
830 [CLKID_AHB_CTRL_BUS
] = &meson8b_ahb_ctrl_bus
.hw
,
831 [CLKID_HDMI_INTR_SYNC
] = &meson8b_hdmi_intr_sync
.hw
,
832 [CLKID_HDMI_PCLK
] = &meson8b_hdmi_pclk
.hw
,
833 [CLKID_USB1_DDR_BRIDGE
] = &meson8b_usb1_ddr_bridge
.hw
,
834 [CLKID_USB0_DDR_BRIDGE
] = &meson8b_usb0_ddr_bridge
.hw
,
835 [CLKID_MMC_PCLK
] = &meson8b_mmc_pclk
.hw
,
836 [CLKID_DVIN
] = &meson8b_dvin
.hw
,
837 [CLKID_UART2
] = &meson8b_uart2
.hw
,
838 [CLKID_SANA
] = &meson8b_sana
.hw
,
839 [CLKID_VPU_INTR
] = &meson8b_vpu_intr
.hw
,
840 [CLKID_SEC_AHB_AHB3_BRIDGE
] = &meson8b_sec_ahb_ahb3_bridge
.hw
,
841 [CLKID_CLK81_A9
] = &meson8b_clk81_a9
.hw
,
842 [CLKID_VCLK2_VENCI0
] = &meson8b_vclk2_venci0
.hw
,
843 [CLKID_VCLK2_VENCI1
] = &meson8b_vclk2_venci1
.hw
,
844 [CLKID_VCLK2_VENCP0
] = &meson8b_vclk2_vencp0
.hw
,
845 [CLKID_VCLK2_VENCP1
] = &meson8b_vclk2_vencp1
.hw
,
846 [CLKID_GCLK_VENCI_INT
] = &meson8b_gclk_venci_int
.hw
,
847 [CLKID_GCLK_VENCP_INT
] = &meson8b_gclk_vencp_int
.hw
,
848 [CLKID_DAC_CLK
] = &meson8b_dac_clk
.hw
,
849 [CLKID_AOCLK_GATE
] = &meson8b_aoclk_gate
.hw
,
850 [CLKID_IEC958_GATE
] = &meson8b_iec958_gate
.hw
,
851 [CLKID_ENC480P
] = &meson8b_enc480p
.hw
,
852 [CLKID_RNG1
] = &meson8b_rng1
.hw
,
853 [CLKID_GCLK_VENCL_INT
] = &meson8b_gclk_vencl_int
.hw
,
854 [CLKID_VCLK2_VENCLMCC
] = &meson8b_vclk2_venclmcc
.hw
,
855 [CLKID_VCLK2_VENCL
] = &meson8b_vclk2_vencl
.hw
,
856 [CLKID_VCLK2_OTHER
] = &meson8b_vclk2_other
.hw
,
857 [CLKID_EDP
] = &meson8b_edp
.hw
,
858 [CLKID_AO_MEDIA_CPU
] = &meson8b_ao_media_cpu
.hw
,
859 [CLKID_AO_AHB_SRAM
] = &meson8b_ao_ahb_sram
.hw
,
860 [CLKID_AO_AHB_BUS
] = &meson8b_ao_ahb_bus
.hw
,
861 [CLKID_AO_IFACE
] = &meson8b_ao_iface
.hw
,
862 [CLKID_MPLL0
] = &meson8b_mpll0
.hw
,
863 [CLKID_MPLL1
] = &meson8b_mpll1
.hw
,
864 [CLKID_MPLL2
] = &meson8b_mpll2
.hw
,
865 [CLKID_MPLL0_DIV
] = &meson8b_mpll0_div
.hw
,
866 [CLKID_MPLL1_DIV
] = &meson8b_mpll1_div
.hw
,
867 [CLKID_MPLL2_DIV
] = &meson8b_mpll2_div
.hw
,
868 [CLKID_CPU_IN_SEL
] = &meson8b_cpu_in_sel
.hw
,
869 [CLKID_CPU_DIV2
] = &meson8b_cpu_div2
.hw
,
870 [CLKID_CPU_DIV3
] = &meson8b_cpu_div3
.hw
,
871 [CLKID_CPU_SCALE_DIV
] = &meson8b_cpu_scale_div
.hw
,
872 [CLKID_CPU_SCALE_OUT_SEL
] = &meson8b_cpu_scale_out_sel
.hw
,
873 [CLKID_MPLL_PREDIV
] = &meson8b_mpll_prediv
.hw
,
874 [CLKID_FCLK_DIV2_DIV
] = &meson8b_fclk_div2_div
.hw
,
875 [CLKID_FCLK_DIV3_DIV
] = &meson8b_fclk_div3_div
.hw
,
876 [CLKID_FCLK_DIV4_DIV
] = &meson8b_fclk_div4_div
.hw
,
877 [CLKID_FCLK_DIV5_DIV
] = &meson8b_fclk_div5_div
.hw
,
878 [CLKID_FCLK_DIV7_DIV
] = &meson8b_fclk_div7_div
.hw
,
879 [CLKID_NAND_SEL
] = &meson8b_nand_clk_sel
.hw
,
880 [CLKID_NAND_DIV
] = &meson8b_nand_clk_div
.hw
,
881 [CLKID_NAND_CLK
] = &meson8b_nand_clk_gate
.hw
,
882 [CLK_NR_CLKS
] = NULL
,
887 static struct clk_regmap
*const meson8b_clk_regmaps
[] = {
906 &meson8b_assist_misc
,
917 &meson8b_mixer_iface
,
933 &meson8b_ahb_data_bus
,
934 &meson8b_ahb_ctrl_bus
,
935 &meson8b_hdmi_intr_sync
,
937 &meson8b_usb1_ddr_bridge
,
938 &meson8b_usb0_ddr_bridge
,
944 &meson8b_sec_ahb_ahb3_bridge
,
946 &meson8b_vclk2_venci0
,
947 &meson8b_vclk2_venci1
,
948 &meson8b_vclk2_vencp0
,
949 &meson8b_vclk2_vencp1
,
950 &meson8b_gclk_venci_int
,
951 &meson8b_gclk_vencp_int
,
954 &meson8b_iec958_gate
,
957 &meson8b_gclk_vencl_int
,
958 &meson8b_vclk2_venclmcc
,
959 &meson8b_vclk2_vencl
,
960 &meson8b_vclk2_other
,
962 &meson8b_ao_media_cpu
,
963 &meson8b_ao_ahb_sram
,
966 &meson8b_mpeg_clk_div
,
967 &meson8b_mpeg_clk_sel
,
978 &meson8b_cpu_scale_div
,
979 &meson8b_cpu_scale_out_sel
,
981 &meson8b_mpll_prediv
,
987 &meson8b_nand_clk_sel
,
988 &meson8b_nand_clk_div
,
989 &meson8b_nand_clk_gate
,
992 static const struct meson8b_clk_reset_line
{
995 } meson8b_clk_reset_bits
[] = {
996 [CLKC_RESET_L2_CACHE_SOFT_RESET
] = {
997 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 30
999 [CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET
] = {
1000 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 29
1002 [CLKC_RESET_SCU_SOFT_RESET
] = {
1003 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 28
1005 [CLKC_RESET_CPU3_SOFT_RESET
] = {
1006 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 27
1008 [CLKC_RESET_CPU2_SOFT_RESET
] = {
1009 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 26
1011 [CLKC_RESET_CPU1_SOFT_RESET
] = {
1012 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 25
1014 [CLKC_RESET_CPU0_SOFT_RESET
] = {
1015 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 24
1017 [CLKC_RESET_A5_GLOBAL_RESET
] = {
1018 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 18
1020 [CLKC_RESET_A5_AXI_SOFT_RESET
] = {
1021 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 17
1023 [CLKC_RESET_A5_ABP_SOFT_RESET
] = {
1024 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 16
1026 [CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET
] = {
1027 .reg
= HHI_SYS_CPU_CLK_CNTL1
, .bit_idx
= 30
1029 [CLKC_RESET_VID_CLK_CNTL_SOFT_RESET
] = {
1030 .reg
= HHI_VID_CLK_CNTL
, .bit_idx
= 15
1032 [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST
] = {
1033 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 7
1035 [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE
] = {
1036 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 3
1038 [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST
] = {
1039 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 1
1041 [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE
] = {
1042 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 0
1046 static int meson8b_clk_reset_update(struct reset_controller_dev
*rcdev
,
1047 unsigned long id
, bool assert)
1049 struct meson8b_clk_reset
*meson8b_clk_reset
=
1050 container_of(rcdev
, struct meson8b_clk_reset
, reset
);
1051 unsigned long flags
;
1052 const struct meson8b_clk_reset_line
*reset
;
1055 if (id
>= ARRAY_SIZE(meson8b_clk_reset_bits
))
1058 reset
= &meson8b_clk_reset_bits
[id
];
1060 spin_lock_irqsave(&meson_clk_lock
, flags
);
1062 val
= readl(meson8b_clk_reset
->base
+ reset
->reg
);
1064 val
|= BIT(reset
->bit_idx
);
1066 val
&= ~BIT(reset
->bit_idx
);
1067 writel(val
, meson8b_clk_reset
->base
+ reset
->reg
);
1069 spin_unlock_irqrestore(&meson_clk_lock
, flags
);
1074 static int meson8b_clk_reset_assert(struct reset_controller_dev
*rcdev
,
1077 return meson8b_clk_reset_update(rcdev
, id
, true);
1080 static int meson8b_clk_reset_deassert(struct reset_controller_dev
*rcdev
,
1083 return meson8b_clk_reset_update(rcdev
, id
, false);
1086 static const struct reset_control_ops meson8b_clk_reset_ops
= {
1087 .assert = meson8b_clk_reset_assert
,
1088 .deassert
= meson8b_clk_reset_deassert
,
1091 static const struct regmap_config clkc_regmap_config
= {
1097 static int meson8b_clkc_probe(struct platform_device
*pdev
)
1100 struct device
*dev
= &pdev
->dev
;
1106 map
= devm_regmap_init_mmio(dev
, clk_base
, &clkc_regmap_config
);
1108 return PTR_ERR(map
);
1110 /* Populate regmap for the regmap backed clocks */
1111 for (i
= 0; i
< ARRAY_SIZE(meson8b_clk_regmaps
); i
++)
1112 meson8b_clk_regmaps
[i
]->map
= map
;
1116 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
1118 for (i
= CLKID_XTAL
; i
< CLK_NR_CLKS
; i
++) {
1119 /* array might be sparse */
1120 if (!meson8b_hw_onecell_data
.hws
[i
])
1123 ret
= devm_clk_hw_register(dev
, meson8b_hw_onecell_data
.hws
[i
]);
1128 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
,
1129 &meson8b_hw_onecell_data
);
1132 static const struct of_device_id meson8b_clkc_match_table
[] = {
1133 { .compatible
= "amlogic,meson8-clkc" },
1134 { .compatible
= "amlogic,meson8b-clkc" },
1135 { .compatible
= "amlogic,meson8m2-clkc" },
1139 static struct platform_driver meson8b_driver
= {
1140 .probe
= meson8b_clkc_probe
,
1142 .name
= "meson8b-clkc",
1143 .of_match_table
= meson8b_clkc_match_table
,
1147 builtin_platform_driver(meson8b_driver
);
1149 static void __init
meson8b_clkc_reset_init(struct device_node
*np
)
1151 struct meson8b_clk_reset
*rstc
;
1154 /* Generic clocks, PLLs and some of the reset-bits */
1155 clk_base
= of_iomap(np
, 1);
1157 pr_err("%s: Unable to map clk base\n", __func__
);
1161 rstc
= kzalloc(sizeof(*rstc
), GFP_KERNEL
);
1165 /* Reset Controller */
1166 rstc
->base
= clk_base
;
1167 rstc
->reset
.ops
= &meson8b_clk_reset_ops
;
1168 rstc
->reset
.nr_resets
= ARRAY_SIZE(meson8b_clk_reset_bits
);
1169 rstc
->reset
.of_node
= np
;
1170 ret
= reset_controller_register(&rstc
->reset
);
1172 pr_err("%s: Failed to register clkc reset controller: %d\n",
1178 CLK_OF_DECLARE_DRIVER(meson8_clkc
, "amlogic,meson8-clkc",
1179 meson8b_clkc_reset_init
);
1180 CLK_OF_DECLARE_DRIVER(meson8b_clkc
, "amlogic,meson8b-clkc",
1181 meson8b_clkc_reset_init
);
1182 CLK_OF_DECLARE_DRIVER(meson8m2_clkc
, "amlogic,meson8m2-clkc",
1183 meson8b_clkc_reset_init
);