2 * AmLogic S802 (Meson8) / S805 (Meson8b) / S812 (Meson8m2) Clock Controller
5 * Copyright (c) 2015 Endless Mobile, Inc.
6 * Author: Carlo Caione <carlo@endlessm.com>
8 * Copyright (c) 2016 BayLibre, Inc.
9 * Michael Turquette <mturquette@baylibre.com>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms and conditions of the GNU General Public License,
13 * version 2, as published by the Free Software Foundation.
15 * This program is distributed in the hope it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
24 #include <linux/clk.h>
25 #include <linux/clk-provider.h>
26 #include <linux/init.h>
27 #include <linux/of_address.h>
28 #include <linux/platform_device.h>
29 #include <linux/reset-controller.h>
30 #include <linux/slab.h>
31 #include <linux/regmap.h>
35 #include "clk-regmap.h"
37 static DEFINE_SPINLOCK(meson_clk_lock
);
39 static void __iomem
*clk_base
;
41 struct meson8b_clk_reset
{
42 struct reset_controller_dev reset
;
46 static const struct pll_rate_table sys_pll_rate_table
[] = {
47 PLL_RATE(312000000, 52, 1, 2),
48 PLL_RATE(336000000, 56, 1, 2),
49 PLL_RATE(360000000, 60, 1, 2),
50 PLL_RATE(384000000, 64, 1, 2),
51 PLL_RATE(408000000, 68, 1, 2),
52 PLL_RATE(432000000, 72, 1, 2),
53 PLL_RATE(456000000, 76, 1, 2),
54 PLL_RATE(480000000, 80, 1, 2),
55 PLL_RATE(504000000, 84, 1, 2),
56 PLL_RATE(528000000, 88, 1, 2),
57 PLL_RATE(552000000, 92, 1, 2),
58 PLL_RATE(576000000, 96, 1, 2),
59 PLL_RATE(600000000, 50, 1, 1),
60 PLL_RATE(624000000, 52, 1, 1),
61 PLL_RATE(648000000, 54, 1, 1),
62 PLL_RATE(672000000, 56, 1, 1),
63 PLL_RATE(696000000, 58, 1, 1),
64 PLL_RATE(720000000, 60, 1, 1),
65 PLL_RATE(744000000, 62, 1, 1),
66 PLL_RATE(768000000, 64, 1, 1),
67 PLL_RATE(792000000, 66, 1, 1),
68 PLL_RATE(816000000, 68, 1, 1),
69 PLL_RATE(840000000, 70, 1, 1),
70 PLL_RATE(864000000, 72, 1, 1),
71 PLL_RATE(888000000, 74, 1, 1),
72 PLL_RATE(912000000, 76, 1, 1),
73 PLL_RATE(936000000, 78, 1, 1),
74 PLL_RATE(960000000, 80, 1, 1),
75 PLL_RATE(984000000, 82, 1, 1),
76 PLL_RATE(1008000000, 84, 1, 1),
77 PLL_RATE(1032000000, 86, 1, 1),
78 PLL_RATE(1056000000, 88, 1, 1),
79 PLL_RATE(1080000000, 90, 1, 1),
80 PLL_RATE(1104000000, 92, 1, 1),
81 PLL_RATE(1128000000, 94, 1, 1),
82 PLL_RATE(1152000000, 96, 1, 1),
83 PLL_RATE(1176000000, 98, 1, 1),
84 PLL_RATE(1200000000, 50, 1, 0),
85 PLL_RATE(1224000000, 51, 1, 0),
86 PLL_RATE(1248000000, 52, 1, 0),
87 PLL_RATE(1272000000, 53, 1, 0),
88 PLL_RATE(1296000000, 54, 1, 0),
89 PLL_RATE(1320000000, 55, 1, 0),
90 PLL_RATE(1344000000, 56, 1, 0),
91 PLL_RATE(1368000000, 57, 1, 0),
92 PLL_RATE(1392000000, 58, 1, 0),
93 PLL_RATE(1416000000, 59, 1, 0),
94 PLL_RATE(1440000000, 60, 1, 0),
95 PLL_RATE(1464000000, 61, 1, 0),
96 PLL_RATE(1488000000, 62, 1, 0),
97 PLL_RATE(1512000000, 63, 1, 0),
98 PLL_RATE(1536000000, 64, 1, 0),
102 static struct clk_fixed_rate meson8b_xtal
= {
103 .fixed_rate
= 24000000,
104 .hw
.init
= &(struct clk_init_data
){
107 .ops
= &clk_fixed_rate_ops
,
111 static struct clk_regmap meson8b_fixed_pll
= {
112 .data
= &(struct meson_clk_pll_data
){
114 .reg_off
= HHI_MPLL_CNTL
,
119 .reg_off
= HHI_MPLL_CNTL
,
124 .reg_off
= HHI_MPLL_CNTL
,
129 .reg_off
= HHI_MPLL_CNTL2
,
134 .reg_off
= HHI_MPLL_CNTL
,
139 .reg_off
= HHI_MPLL_CNTL
,
144 .hw
.init
= &(struct clk_init_data
){
146 .ops
= &meson_clk_pll_ro_ops
,
147 .parent_names
= (const char *[]){ "xtal" },
149 .flags
= CLK_GET_RATE_NOCACHE
,
153 static struct clk_regmap meson8b_vid_pll
= {
154 .data
= &(struct meson_clk_pll_data
){
156 .reg_off
= HHI_VID_PLL_CNTL
,
161 .reg_off
= HHI_VID_PLL_CNTL
,
166 .reg_off
= HHI_VID_PLL_CNTL
,
171 .reg_off
= HHI_VID_PLL_CNTL
,
176 .reg_off
= HHI_VID_PLL_CNTL
,
181 .hw
.init
= &(struct clk_init_data
){
183 .ops
= &meson_clk_pll_ro_ops
,
184 .parent_names
= (const char *[]){ "xtal" },
186 .flags
= CLK_GET_RATE_NOCACHE
,
190 static struct clk_regmap meson8b_sys_pll
= {
191 .data
= &(struct meson_clk_pll_data
){
193 .reg_off
= HHI_SYS_PLL_CNTL
,
198 .reg_off
= HHI_SYS_PLL_CNTL
,
203 .reg_off
= HHI_SYS_PLL_CNTL
,
208 .reg_off
= HHI_SYS_PLL_CNTL
,
213 .reg_off
= HHI_SYS_PLL_CNTL
,
217 .table
= sys_pll_rate_table
,
219 .hw
.init
= &(struct clk_init_data
){
221 .ops
= &meson_clk_pll_ro_ops
,
222 .parent_names
= (const char *[]){ "xtal" },
224 .flags
= CLK_GET_RATE_NOCACHE
,
228 static struct clk_fixed_factor meson8b_fclk_div2_div
= {
231 .hw
.init
= &(struct clk_init_data
){
232 .name
= "fclk_div2_div",
233 .ops
= &clk_fixed_factor_ops
,
234 .parent_names
= (const char *[]){ "fixed_pll" },
239 static struct clk_regmap meson8b_fclk_div2
= {
240 .data
= &(struct clk_regmap_gate_data
){
241 .offset
= HHI_MPLL_CNTL6
,
244 .hw
.init
= &(struct clk_init_data
){
246 .ops
= &clk_regmap_gate_ops
,
247 .parent_names
= (const char *[]){ "fclk_div2_div" },
252 static struct clk_fixed_factor meson8b_fclk_div3_div
= {
255 .hw
.init
= &(struct clk_init_data
){
256 .name
= "fclk_div3_div",
257 .ops
= &clk_fixed_factor_ops
,
258 .parent_names
= (const char *[]){ "fixed_pll" },
263 static struct clk_regmap meson8b_fclk_div3
= {
264 .data
= &(struct clk_regmap_gate_data
){
265 .offset
= HHI_MPLL_CNTL6
,
268 .hw
.init
= &(struct clk_init_data
){
270 .ops
= &clk_regmap_gate_ops
,
271 .parent_names
= (const char *[]){ "fclk_div3_div" },
276 static struct clk_fixed_factor meson8b_fclk_div4_div
= {
279 .hw
.init
= &(struct clk_init_data
){
280 .name
= "fclk_div4_div",
281 .ops
= &clk_fixed_factor_ops
,
282 .parent_names
= (const char *[]){ "fixed_pll" },
287 static struct clk_regmap meson8b_fclk_div4
= {
288 .data
= &(struct clk_regmap_gate_data
){
289 .offset
= HHI_MPLL_CNTL6
,
292 .hw
.init
= &(struct clk_init_data
){
294 .ops
= &clk_regmap_gate_ops
,
295 .parent_names
= (const char *[]){ "fclk_div4_div" },
300 static struct clk_fixed_factor meson8b_fclk_div5_div
= {
303 .hw
.init
= &(struct clk_init_data
){
304 .name
= "fclk_div5_div",
305 .ops
= &clk_fixed_factor_ops
,
306 .parent_names
= (const char *[]){ "fixed_pll" },
311 static struct clk_regmap meson8b_fclk_div5
= {
312 .data
= &(struct clk_regmap_gate_data
){
313 .offset
= HHI_MPLL_CNTL6
,
316 .hw
.init
= &(struct clk_init_data
){
318 .ops
= &clk_regmap_gate_ops
,
319 .parent_names
= (const char *[]){ "fclk_div5_div" },
324 static struct clk_fixed_factor meson8b_fclk_div7_div
= {
327 .hw
.init
= &(struct clk_init_data
){
328 .name
= "fclk_div7_div",
329 .ops
= &clk_fixed_factor_ops
,
330 .parent_names
= (const char *[]){ "fixed_pll" },
335 static struct clk_regmap meson8b_fclk_div7
= {
336 .data
= &(struct clk_regmap_gate_data
){
337 .offset
= HHI_MPLL_CNTL6
,
340 .hw
.init
= &(struct clk_init_data
){
342 .ops
= &clk_regmap_gate_ops
,
343 .parent_names
= (const char *[]){ "fclk_div7_div" },
348 static struct clk_regmap meson8b_mpll_prediv
= {
349 .data
= &(struct clk_regmap_div_data
){
350 .offset
= HHI_MPLL_CNTL5
,
354 .hw
.init
= &(struct clk_init_data
){
355 .name
= "mpll_prediv",
356 .ops
= &clk_regmap_divider_ro_ops
,
357 .parent_names
= (const char *[]){ "fixed_pll" },
362 static struct clk_regmap meson8b_mpll0_div
= {
363 .data
= &(struct meson_clk_mpll_data
){
365 .reg_off
= HHI_MPLL_CNTL7
,
370 .reg_off
= HHI_MPLL_CNTL7
,
375 .reg_off
= HHI_MPLL_CNTL7
,
380 .reg_off
= HHI_MPLL_CNTL
,
384 .lock
= &meson_clk_lock
,
386 .hw
.init
= &(struct clk_init_data
){
388 .ops
= &meson_clk_mpll_ops
,
389 .parent_names
= (const char *[]){ "mpll_prediv" },
394 static struct clk_regmap meson8b_mpll0
= {
395 .data
= &(struct clk_regmap_gate_data
){
396 .offset
= HHI_MPLL_CNTL7
,
399 .hw
.init
= &(struct clk_init_data
){
401 .ops
= &clk_regmap_gate_ops
,
402 .parent_names
= (const char *[]){ "mpll0_div" },
404 .flags
= CLK_SET_RATE_PARENT
,
408 static struct clk_regmap meson8b_mpll1_div
= {
409 .data
= &(struct meson_clk_mpll_data
){
411 .reg_off
= HHI_MPLL_CNTL8
,
416 .reg_off
= HHI_MPLL_CNTL8
,
421 .reg_off
= HHI_MPLL_CNTL8
,
425 .lock
= &meson_clk_lock
,
427 .hw
.init
= &(struct clk_init_data
){
429 .ops
= &meson_clk_mpll_ops
,
430 .parent_names
= (const char *[]){ "mpll_prediv" },
435 static struct clk_regmap meson8b_mpll1
= {
436 .data
= &(struct clk_regmap_gate_data
){
437 .offset
= HHI_MPLL_CNTL8
,
440 .hw
.init
= &(struct clk_init_data
){
442 .ops
= &clk_regmap_gate_ops
,
443 .parent_names
= (const char *[]){ "mpll1_div" },
445 .flags
= CLK_SET_RATE_PARENT
,
449 static struct clk_regmap meson8b_mpll2_div
= {
450 .data
= &(struct meson_clk_mpll_data
){
452 .reg_off
= HHI_MPLL_CNTL9
,
457 .reg_off
= HHI_MPLL_CNTL9
,
462 .reg_off
= HHI_MPLL_CNTL9
,
466 .lock
= &meson_clk_lock
,
468 .hw
.init
= &(struct clk_init_data
){
470 .ops
= &meson_clk_mpll_ops
,
471 .parent_names
= (const char *[]){ "mpll_prediv" },
476 static struct clk_regmap meson8b_mpll2
= {
477 .data
= &(struct clk_regmap_gate_data
){
478 .offset
= HHI_MPLL_CNTL9
,
481 .hw
.init
= &(struct clk_init_data
){
483 .ops
= &clk_regmap_gate_ops
,
484 .parent_names
= (const char *[]){ "mpll2_div" },
486 .flags
= CLK_SET_RATE_PARENT
,
490 static u32 mux_table_clk81
[] = { 6, 5, 7 };
491 static struct clk_regmap meson8b_mpeg_clk_sel
= {
492 .data
= &(struct clk_regmap_mux_data
){
493 .offset
= HHI_MPEG_CLK_CNTL
,
496 .table
= mux_table_clk81
,
498 .hw
.init
= &(struct clk_init_data
){
499 .name
= "mpeg_clk_sel",
500 .ops
= &clk_regmap_mux_ro_ops
,
502 * FIXME bits 14:12 selects from 8 possible parents:
503 * xtal, 1'b0 (wtf), fclk_div7, mpll_clkout1, mpll_clkout2,
504 * fclk_div4, fclk_div3, fclk_div5
506 .parent_names
= (const char *[]){ "fclk_div3", "fclk_div4",
512 static struct clk_regmap meson8b_mpeg_clk_div
= {
513 .data
= &(struct clk_regmap_div_data
){
514 .offset
= HHI_MPEG_CLK_CNTL
,
518 .hw
.init
= &(struct clk_init_data
){
519 .name
= "mpeg_clk_div",
520 .ops
= &clk_regmap_divider_ro_ops
,
521 .parent_names
= (const char *[]){ "mpeg_clk_sel" },
526 static struct clk_regmap meson8b_clk81
= {
527 .data
= &(struct clk_regmap_gate_data
){
528 .offset
= HHI_MPEG_CLK_CNTL
,
531 .hw
.init
= &(struct clk_init_data
){
533 .ops
= &clk_regmap_gate_ops
,
534 .parent_names
= (const char *[]){ "mpeg_clk_div" },
536 .flags
= CLK_IS_CRITICAL
,
540 static struct clk_regmap meson8b_cpu_in_sel
= {
541 .data
= &(struct clk_regmap_mux_data
){
542 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
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" },
551 .flags
= (CLK_SET_RATE_PARENT
|
552 CLK_SET_RATE_NO_REPARENT
),
556 static struct clk_fixed_factor meson8b_cpu_div2
= {
559 .hw
.init
= &(struct clk_init_data
){
561 .ops
= &clk_fixed_factor_ops
,
562 .parent_names
= (const char *[]){ "cpu_in_sel" },
564 .flags
= CLK_SET_RATE_PARENT
,
568 static struct clk_fixed_factor meson8b_cpu_div3
= {
571 .hw
.init
= &(struct clk_init_data
){
573 .ops
= &clk_fixed_factor_ops
,
574 .parent_names
= (const char *[]){ "cpu_in_sel" },
576 .flags
= CLK_SET_RATE_PARENT
,
580 static 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 },
591 static struct clk_regmap meson8b_cpu_scale_div
= {
592 .data
= &(struct clk_regmap_div_data
){
593 .offset
= HHI_SYS_CPU_CLK_CNTL1
,
596 .table
= cpu_scale_table
,
597 .flags
= CLK_DIVIDER_ALLOW_ZERO
,
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" },
604 .flags
= CLK_SET_RATE_PARENT
,
608 static struct clk_regmap meson8b_cpu_scale_out_sel
= {
609 .data
= &(struct clk_regmap_mux_data
){
610 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
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",
622 .flags
= CLK_SET_RATE_PARENT
,
626 static struct clk_regmap meson8b_cpu_clk
= {
627 .data
= &(struct clk_regmap_mux_data
){
628 .offset
= HHI_SYS_CPU_CLK_CNTL0
,
632 .hw
.init
= &(struct clk_init_data
){
634 .ops
= &clk_regmap_mux_ro_ops
,
635 .parent_names
= (const char *[]){ "xtal", "cpu_out_sel" },
637 .flags
= (CLK_SET_RATE_PARENT
|
638 CLK_SET_RATE_NO_REPARENT
),
642 /* Everything Else (EE) domain gates */
644 static MESON_GATE(meson8b_ddr
, HHI_GCLK_MPEG0
, 0);
645 static MESON_GATE(meson8b_dos
, HHI_GCLK_MPEG0
, 1);
646 static MESON_GATE(meson8b_isa
, HHI_GCLK_MPEG0
, 5);
647 static MESON_GATE(meson8b_pl301
, HHI_GCLK_MPEG0
, 6);
648 static MESON_GATE(meson8b_periphs
, HHI_GCLK_MPEG0
, 7);
649 static MESON_GATE(meson8b_spicc
, HHI_GCLK_MPEG0
, 8);
650 static MESON_GATE(meson8b_i2c
, HHI_GCLK_MPEG0
, 9);
651 static MESON_GATE(meson8b_sar_adc
, HHI_GCLK_MPEG0
, 10);
652 static MESON_GATE(meson8b_smart_card
, HHI_GCLK_MPEG0
, 11);
653 static MESON_GATE(meson8b_rng0
, HHI_GCLK_MPEG0
, 12);
654 static MESON_GATE(meson8b_uart0
, HHI_GCLK_MPEG0
, 13);
655 static MESON_GATE(meson8b_sdhc
, HHI_GCLK_MPEG0
, 14);
656 static MESON_GATE(meson8b_stream
, HHI_GCLK_MPEG0
, 15);
657 static MESON_GATE(meson8b_async_fifo
, HHI_GCLK_MPEG0
, 16);
658 static MESON_GATE(meson8b_sdio
, HHI_GCLK_MPEG0
, 17);
659 static MESON_GATE(meson8b_abuf
, HHI_GCLK_MPEG0
, 18);
660 static MESON_GATE(meson8b_hiu_iface
, HHI_GCLK_MPEG0
, 19);
661 static MESON_GATE(meson8b_assist_misc
, HHI_GCLK_MPEG0
, 23);
662 static MESON_GATE(meson8b_spi
, HHI_GCLK_MPEG0
, 30);
664 static MESON_GATE(meson8b_i2s_spdif
, HHI_GCLK_MPEG1
, 2);
665 static MESON_GATE(meson8b_eth
, HHI_GCLK_MPEG1
, 3);
666 static MESON_GATE(meson8b_demux
, HHI_GCLK_MPEG1
, 4);
667 static MESON_GATE(meson8b_aiu_glue
, HHI_GCLK_MPEG1
, 6);
668 static MESON_GATE(meson8b_iec958
, HHI_GCLK_MPEG1
, 7);
669 static MESON_GATE(meson8b_i2s_out
, HHI_GCLK_MPEG1
, 8);
670 static MESON_GATE(meson8b_amclk
, HHI_GCLK_MPEG1
, 9);
671 static MESON_GATE(meson8b_aififo2
, HHI_GCLK_MPEG1
, 10);
672 static MESON_GATE(meson8b_mixer
, HHI_GCLK_MPEG1
, 11);
673 static MESON_GATE(meson8b_mixer_iface
, HHI_GCLK_MPEG1
, 12);
674 static MESON_GATE(meson8b_adc
, HHI_GCLK_MPEG1
, 13);
675 static MESON_GATE(meson8b_blkmv
, HHI_GCLK_MPEG1
, 14);
676 static MESON_GATE(meson8b_aiu
, HHI_GCLK_MPEG1
, 15);
677 static MESON_GATE(meson8b_uart1
, HHI_GCLK_MPEG1
, 16);
678 static MESON_GATE(meson8b_g2d
, HHI_GCLK_MPEG1
, 20);
679 static MESON_GATE(meson8b_usb0
, HHI_GCLK_MPEG1
, 21);
680 static MESON_GATE(meson8b_usb1
, HHI_GCLK_MPEG1
, 22);
681 static MESON_GATE(meson8b_reset
, HHI_GCLK_MPEG1
, 23);
682 static MESON_GATE(meson8b_nand
, HHI_GCLK_MPEG1
, 24);
683 static MESON_GATE(meson8b_dos_parser
, HHI_GCLK_MPEG1
, 25);
684 static MESON_GATE(meson8b_usb
, HHI_GCLK_MPEG1
, 26);
685 static MESON_GATE(meson8b_vdin1
, HHI_GCLK_MPEG1
, 28);
686 static MESON_GATE(meson8b_ahb_arb0
, HHI_GCLK_MPEG1
, 29);
687 static MESON_GATE(meson8b_efuse
, HHI_GCLK_MPEG1
, 30);
688 static MESON_GATE(meson8b_boot_rom
, HHI_GCLK_MPEG1
, 31);
690 static MESON_GATE(meson8b_ahb_data_bus
, HHI_GCLK_MPEG2
, 1);
691 static MESON_GATE(meson8b_ahb_ctrl_bus
, HHI_GCLK_MPEG2
, 2);
692 static MESON_GATE(meson8b_hdmi_intr_sync
, HHI_GCLK_MPEG2
, 3);
693 static MESON_GATE(meson8b_hdmi_pclk
, HHI_GCLK_MPEG2
, 4);
694 static MESON_GATE(meson8b_usb1_ddr_bridge
, HHI_GCLK_MPEG2
, 8);
695 static MESON_GATE(meson8b_usb0_ddr_bridge
, HHI_GCLK_MPEG2
, 9);
696 static MESON_GATE(meson8b_mmc_pclk
, HHI_GCLK_MPEG2
, 11);
697 static MESON_GATE(meson8b_dvin
, HHI_GCLK_MPEG2
, 12);
698 static MESON_GATE(meson8b_uart2
, HHI_GCLK_MPEG2
, 15);
699 static MESON_GATE(meson8b_sana
, HHI_GCLK_MPEG2
, 22);
700 static MESON_GATE(meson8b_vpu_intr
, HHI_GCLK_MPEG2
, 25);
701 static MESON_GATE(meson8b_sec_ahb_ahb3_bridge
, HHI_GCLK_MPEG2
, 26);
702 static MESON_GATE(meson8b_clk81_a9
, HHI_GCLK_MPEG2
, 29);
704 static MESON_GATE(meson8b_vclk2_venci0
, HHI_GCLK_OTHER
, 1);
705 static MESON_GATE(meson8b_vclk2_venci1
, HHI_GCLK_OTHER
, 2);
706 static MESON_GATE(meson8b_vclk2_vencp0
, HHI_GCLK_OTHER
, 3);
707 static MESON_GATE(meson8b_vclk2_vencp1
, HHI_GCLK_OTHER
, 4);
708 static MESON_GATE(meson8b_gclk_venci_int
, HHI_GCLK_OTHER
, 8);
709 static MESON_GATE(meson8b_gclk_vencp_int
, HHI_GCLK_OTHER
, 9);
710 static MESON_GATE(meson8b_dac_clk
, HHI_GCLK_OTHER
, 10);
711 static MESON_GATE(meson8b_aoclk_gate
, HHI_GCLK_OTHER
, 14);
712 static MESON_GATE(meson8b_iec958_gate
, HHI_GCLK_OTHER
, 16);
713 static MESON_GATE(meson8b_enc480p
, HHI_GCLK_OTHER
, 20);
714 static MESON_GATE(meson8b_rng1
, HHI_GCLK_OTHER
, 21);
715 static MESON_GATE(meson8b_gclk_vencl_int
, HHI_GCLK_OTHER
, 22);
716 static MESON_GATE(meson8b_vclk2_venclmcc
, HHI_GCLK_OTHER
, 24);
717 static MESON_GATE(meson8b_vclk2_vencl
, HHI_GCLK_OTHER
, 25);
718 static MESON_GATE(meson8b_vclk2_other
, HHI_GCLK_OTHER
, 26);
719 static MESON_GATE(meson8b_edp
, HHI_GCLK_OTHER
, 31);
721 /* Always On (AO) domain gates */
723 static MESON_GATE(meson8b_ao_media_cpu
, HHI_GCLK_AO
, 0);
724 static MESON_GATE(meson8b_ao_ahb_sram
, HHI_GCLK_AO
, 1);
725 static MESON_GATE(meson8b_ao_ahb_bus
, HHI_GCLK_AO
, 2);
726 static MESON_GATE(meson8b_ao_iface
, HHI_GCLK_AO
, 3);
728 static struct clk_hw_onecell_data meson8b_hw_onecell_data
= {
730 [CLKID_XTAL
] = &meson8b_xtal
.hw
,
731 [CLKID_PLL_FIXED
] = &meson8b_fixed_pll
.hw
,
732 [CLKID_PLL_VID
] = &meson8b_vid_pll
.hw
,
733 [CLKID_PLL_SYS
] = &meson8b_sys_pll
.hw
,
734 [CLKID_FCLK_DIV2
] = &meson8b_fclk_div2
.hw
,
735 [CLKID_FCLK_DIV3
] = &meson8b_fclk_div3
.hw
,
736 [CLKID_FCLK_DIV4
] = &meson8b_fclk_div4
.hw
,
737 [CLKID_FCLK_DIV5
] = &meson8b_fclk_div5
.hw
,
738 [CLKID_FCLK_DIV7
] = &meson8b_fclk_div7
.hw
,
739 [CLKID_CPUCLK
] = &meson8b_cpu_clk
.hw
,
740 [CLKID_MPEG_SEL
] = &meson8b_mpeg_clk_sel
.hw
,
741 [CLKID_MPEG_DIV
] = &meson8b_mpeg_clk_div
.hw
,
742 [CLKID_CLK81
] = &meson8b_clk81
.hw
,
743 [CLKID_DDR
] = &meson8b_ddr
.hw
,
744 [CLKID_DOS
] = &meson8b_dos
.hw
,
745 [CLKID_ISA
] = &meson8b_isa
.hw
,
746 [CLKID_PL301
] = &meson8b_pl301
.hw
,
747 [CLKID_PERIPHS
] = &meson8b_periphs
.hw
,
748 [CLKID_SPICC
] = &meson8b_spicc
.hw
,
749 [CLKID_I2C
] = &meson8b_i2c
.hw
,
750 [CLKID_SAR_ADC
] = &meson8b_sar_adc
.hw
,
751 [CLKID_SMART_CARD
] = &meson8b_smart_card
.hw
,
752 [CLKID_RNG0
] = &meson8b_rng0
.hw
,
753 [CLKID_UART0
] = &meson8b_uart0
.hw
,
754 [CLKID_SDHC
] = &meson8b_sdhc
.hw
,
755 [CLKID_STREAM
] = &meson8b_stream
.hw
,
756 [CLKID_ASYNC_FIFO
] = &meson8b_async_fifo
.hw
,
757 [CLKID_SDIO
] = &meson8b_sdio
.hw
,
758 [CLKID_ABUF
] = &meson8b_abuf
.hw
,
759 [CLKID_HIU_IFACE
] = &meson8b_hiu_iface
.hw
,
760 [CLKID_ASSIST_MISC
] = &meson8b_assist_misc
.hw
,
761 [CLKID_SPI
] = &meson8b_spi
.hw
,
762 [CLKID_I2S_SPDIF
] = &meson8b_i2s_spdif
.hw
,
763 [CLKID_ETH
] = &meson8b_eth
.hw
,
764 [CLKID_DEMUX
] = &meson8b_demux
.hw
,
765 [CLKID_AIU_GLUE
] = &meson8b_aiu_glue
.hw
,
766 [CLKID_IEC958
] = &meson8b_iec958
.hw
,
767 [CLKID_I2S_OUT
] = &meson8b_i2s_out
.hw
,
768 [CLKID_AMCLK
] = &meson8b_amclk
.hw
,
769 [CLKID_AIFIFO2
] = &meson8b_aififo2
.hw
,
770 [CLKID_MIXER
] = &meson8b_mixer
.hw
,
771 [CLKID_MIXER_IFACE
] = &meson8b_mixer_iface
.hw
,
772 [CLKID_ADC
] = &meson8b_adc
.hw
,
773 [CLKID_BLKMV
] = &meson8b_blkmv
.hw
,
774 [CLKID_AIU
] = &meson8b_aiu
.hw
,
775 [CLKID_UART1
] = &meson8b_uart1
.hw
,
776 [CLKID_G2D
] = &meson8b_g2d
.hw
,
777 [CLKID_USB0
] = &meson8b_usb0
.hw
,
778 [CLKID_USB1
] = &meson8b_usb1
.hw
,
779 [CLKID_RESET
] = &meson8b_reset
.hw
,
780 [CLKID_NAND
] = &meson8b_nand
.hw
,
781 [CLKID_DOS_PARSER
] = &meson8b_dos_parser
.hw
,
782 [CLKID_USB
] = &meson8b_usb
.hw
,
783 [CLKID_VDIN1
] = &meson8b_vdin1
.hw
,
784 [CLKID_AHB_ARB0
] = &meson8b_ahb_arb0
.hw
,
785 [CLKID_EFUSE
] = &meson8b_efuse
.hw
,
786 [CLKID_BOOT_ROM
] = &meson8b_boot_rom
.hw
,
787 [CLKID_AHB_DATA_BUS
] = &meson8b_ahb_data_bus
.hw
,
788 [CLKID_AHB_CTRL_BUS
] = &meson8b_ahb_ctrl_bus
.hw
,
789 [CLKID_HDMI_INTR_SYNC
] = &meson8b_hdmi_intr_sync
.hw
,
790 [CLKID_HDMI_PCLK
] = &meson8b_hdmi_pclk
.hw
,
791 [CLKID_USB1_DDR_BRIDGE
] = &meson8b_usb1_ddr_bridge
.hw
,
792 [CLKID_USB0_DDR_BRIDGE
] = &meson8b_usb0_ddr_bridge
.hw
,
793 [CLKID_MMC_PCLK
] = &meson8b_mmc_pclk
.hw
,
794 [CLKID_DVIN
] = &meson8b_dvin
.hw
,
795 [CLKID_UART2
] = &meson8b_uart2
.hw
,
796 [CLKID_SANA
] = &meson8b_sana
.hw
,
797 [CLKID_VPU_INTR
] = &meson8b_vpu_intr
.hw
,
798 [CLKID_SEC_AHB_AHB3_BRIDGE
] = &meson8b_sec_ahb_ahb3_bridge
.hw
,
799 [CLKID_CLK81_A9
] = &meson8b_clk81_a9
.hw
,
800 [CLKID_VCLK2_VENCI0
] = &meson8b_vclk2_venci0
.hw
,
801 [CLKID_VCLK2_VENCI1
] = &meson8b_vclk2_venci1
.hw
,
802 [CLKID_VCLK2_VENCP0
] = &meson8b_vclk2_vencp0
.hw
,
803 [CLKID_VCLK2_VENCP1
] = &meson8b_vclk2_vencp1
.hw
,
804 [CLKID_GCLK_VENCI_INT
] = &meson8b_gclk_venci_int
.hw
,
805 [CLKID_GCLK_VENCP_INT
] = &meson8b_gclk_vencp_int
.hw
,
806 [CLKID_DAC_CLK
] = &meson8b_dac_clk
.hw
,
807 [CLKID_AOCLK_GATE
] = &meson8b_aoclk_gate
.hw
,
808 [CLKID_IEC958_GATE
] = &meson8b_iec958_gate
.hw
,
809 [CLKID_ENC480P
] = &meson8b_enc480p
.hw
,
810 [CLKID_RNG1
] = &meson8b_rng1
.hw
,
811 [CLKID_GCLK_VENCL_INT
] = &meson8b_gclk_vencl_int
.hw
,
812 [CLKID_VCLK2_VENCLMCC
] = &meson8b_vclk2_venclmcc
.hw
,
813 [CLKID_VCLK2_VENCL
] = &meson8b_vclk2_vencl
.hw
,
814 [CLKID_VCLK2_OTHER
] = &meson8b_vclk2_other
.hw
,
815 [CLKID_EDP
] = &meson8b_edp
.hw
,
816 [CLKID_AO_MEDIA_CPU
] = &meson8b_ao_media_cpu
.hw
,
817 [CLKID_AO_AHB_SRAM
] = &meson8b_ao_ahb_sram
.hw
,
818 [CLKID_AO_AHB_BUS
] = &meson8b_ao_ahb_bus
.hw
,
819 [CLKID_AO_IFACE
] = &meson8b_ao_iface
.hw
,
820 [CLKID_MPLL0
] = &meson8b_mpll0
.hw
,
821 [CLKID_MPLL1
] = &meson8b_mpll1
.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
,
837 [CLK_NR_CLKS
] = NULL
,
842 static struct clk_regmap
*const meson8b_clk_regmaps
[] = {
861 &meson8b_assist_misc
,
872 &meson8b_mixer_iface
,
888 &meson8b_ahb_data_bus
,
889 &meson8b_ahb_ctrl_bus
,
890 &meson8b_hdmi_intr_sync
,
892 &meson8b_usb1_ddr_bridge
,
893 &meson8b_usb0_ddr_bridge
,
899 &meson8b_sec_ahb_ahb3_bridge
,
901 &meson8b_vclk2_venci0
,
902 &meson8b_vclk2_venci1
,
903 &meson8b_vclk2_vencp0
,
904 &meson8b_vclk2_vencp1
,
905 &meson8b_gclk_venci_int
,
906 &meson8b_gclk_vencp_int
,
909 &meson8b_iec958_gate
,
912 &meson8b_gclk_vencl_int
,
913 &meson8b_vclk2_venclmcc
,
914 &meson8b_vclk2_vencl
,
915 &meson8b_vclk2_other
,
917 &meson8b_ao_media_cpu
,
918 &meson8b_ao_ahb_sram
,
921 &meson8b_mpeg_clk_div
,
922 &meson8b_mpeg_clk_sel
,
933 &meson8b_cpu_scale_div
,
934 &meson8b_cpu_scale_out_sel
,
936 &meson8b_mpll_prediv
,
944 static const struct meson8b_clk_reset_line
{
947 } meson8b_clk_reset_bits
[] = {
948 [CLKC_RESET_L2_CACHE_SOFT_RESET
] = {
949 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 30
951 [CLKC_RESET_AXI_64_TO_128_BRIDGE_A5_SOFT_RESET
] = {
952 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 29
954 [CLKC_RESET_SCU_SOFT_RESET
] = {
955 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 28
957 [CLKC_RESET_CPU3_SOFT_RESET
] = {
958 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 27
960 [CLKC_RESET_CPU2_SOFT_RESET
] = {
961 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 26
963 [CLKC_RESET_CPU1_SOFT_RESET
] = {
964 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 25
966 [CLKC_RESET_CPU0_SOFT_RESET
] = {
967 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 24
969 [CLKC_RESET_A5_GLOBAL_RESET
] = {
970 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 18
972 [CLKC_RESET_A5_AXI_SOFT_RESET
] = {
973 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 17
975 [CLKC_RESET_A5_ABP_SOFT_RESET
] = {
976 .reg
= HHI_SYS_CPU_CLK_CNTL0
, .bit_idx
= 16
978 [CLKC_RESET_AXI_64_TO_128_BRIDGE_MMC_SOFT_RESET
] = {
979 .reg
= HHI_SYS_CPU_CLK_CNTL1
, .bit_idx
= 30
981 [CLKC_RESET_VID_CLK_CNTL_SOFT_RESET
] = {
982 .reg
= HHI_VID_CLK_CNTL
, .bit_idx
= 15
984 [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_POST
] = {
985 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 7
987 [CLKC_RESET_VID_DIVIDER_CNTL_SOFT_RESET_PRE
] = {
988 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 3
990 [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_POST
] = {
991 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 1
993 [CLKC_RESET_VID_DIVIDER_CNTL_RESET_N_PRE
] = {
994 .reg
= HHI_VID_DIVIDER_CNTL
, .bit_idx
= 0
998 static int meson8b_clk_reset_update(struct reset_controller_dev
*rcdev
,
999 unsigned long id
, bool assert)
1001 struct meson8b_clk_reset
*meson8b_clk_reset
=
1002 container_of(rcdev
, struct meson8b_clk_reset
, reset
);
1003 unsigned long flags
;
1004 const struct meson8b_clk_reset_line
*reset
;
1007 if (id
>= ARRAY_SIZE(meson8b_clk_reset_bits
))
1010 reset
= &meson8b_clk_reset_bits
[id
];
1012 spin_lock_irqsave(&meson_clk_lock
, flags
);
1014 val
= readl(meson8b_clk_reset
->base
+ reset
->reg
);
1016 val
|= BIT(reset
->bit_idx
);
1018 val
&= ~BIT(reset
->bit_idx
);
1019 writel(val
, meson8b_clk_reset
->base
+ reset
->reg
);
1021 spin_unlock_irqrestore(&meson_clk_lock
, flags
);
1026 static int meson8b_clk_reset_assert(struct reset_controller_dev
*rcdev
,
1029 return meson8b_clk_reset_update(rcdev
, id
, true);
1032 static int meson8b_clk_reset_deassert(struct reset_controller_dev
*rcdev
,
1035 return meson8b_clk_reset_update(rcdev
, id
, false);
1038 static const struct reset_control_ops meson8b_clk_reset_ops
= {
1039 .assert = meson8b_clk_reset_assert
,
1040 .deassert
= meson8b_clk_reset_deassert
,
1043 static const struct regmap_config clkc_regmap_config
= {
1049 static int meson8b_clkc_probe(struct platform_device
*pdev
)
1052 struct device
*dev
= &pdev
->dev
;
1058 map
= devm_regmap_init_mmio(dev
, clk_base
, &clkc_regmap_config
);
1060 return PTR_ERR(map
);
1062 /* Populate regmap for the regmap backed clocks */
1063 for (i
= 0; i
< ARRAY_SIZE(meson8b_clk_regmaps
); i
++)
1064 meson8b_clk_regmaps
[i
]->map
= map
;
1068 * CLKID_UNUSED = 0, so skip it and start with CLKID_XTAL = 1
1070 for (i
= CLKID_XTAL
; i
< CLK_NR_CLKS
; i
++) {
1071 /* array might be sparse */
1072 if (!meson8b_hw_onecell_data
.hws
[i
])
1075 ret
= devm_clk_hw_register(dev
, meson8b_hw_onecell_data
.hws
[i
]);
1080 return devm_of_clk_add_hw_provider(dev
, of_clk_hw_onecell_get
,
1081 &meson8b_hw_onecell_data
);
1084 static const struct of_device_id meson8b_clkc_match_table
[] = {
1085 { .compatible
= "amlogic,meson8-clkc" },
1086 { .compatible
= "amlogic,meson8b-clkc" },
1087 { .compatible
= "amlogic,meson8m2-clkc" },
1091 static struct platform_driver meson8b_driver
= {
1092 .probe
= meson8b_clkc_probe
,
1094 .name
= "meson8b-clkc",
1095 .of_match_table
= meson8b_clkc_match_table
,
1099 builtin_platform_driver(meson8b_driver
);
1101 static void __init
meson8b_clkc_reset_init(struct device_node
*np
)
1103 struct meson8b_clk_reset
*rstc
;
1106 /* Generic clocks, PLLs and some of the reset-bits */
1107 clk_base
= of_iomap(np
, 1);
1109 pr_err("%s: Unable to map clk base\n", __func__
);
1113 rstc
= kzalloc(sizeof(*rstc
), GFP_KERNEL
);
1117 /* Reset Controller */
1118 rstc
->base
= clk_base
;
1119 rstc
->reset
.ops
= &meson8b_clk_reset_ops
;
1120 rstc
->reset
.nr_resets
= ARRAY_SIZE(meson8b_clk_reset_bits
);
1121 rstc
->reset
.of_node
= np
;
1122 ret
= reset_controller_register(&rstc
->reset
);
1124 pr_err("%s: Failed to register clkc reset controller: %d\n",
1130 CLK_OF_DECLARE_DRIVER(meson8_clkc
, "amlogic,meson8-clkc",
1131 meson8b_clkc_reset_init
);
1132 CLK_OF_DECLARE_DRIVER(meson8b_clkc
, "amlogic,meson8b-clkc",
1133 meson8b_clkc_reset_init
);
1134 CLK_OF_DECLARE_DRIVER(meson8m2_clkc
, "amlogic,meson8m2-clkc",
1135 meson8b_clkc_reset_init
);