aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/clk/meson
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/clk/meson')
-rw-r--r--drivers/clk/meson/Kconfig101
-rw-r--r--drivers/clk/meson/Makefile29
-rw-r--r--drivers/clk/meson/axg-aoclk.c193
-rw-r--r--drivers/clk/meson/axg-aoclk.h13
-rw-r--r--drivers/clk/meson/axg-audio.c5
-rw-r--r--drivers/clk/meson/axg.c69
-rw-r--r--drivers/clk/meson/clk-dualdiv.c138
-rw-r--r--drivers/clk/meson/clk-dualdiv.h33
-rw-r--r--drivers/clk/meson/clk-input.c7
-rw-r--r--drivers/clk/meson/clk-input.h19
-rw-r--r--drivers/clk/meson/clk-mpll.c12
-rw-r--r--drivers/clk/meson/clk-mpll.h30
-rw-r--r--drivers/clk/meson/clk-phase.c75
-rw-r--r--drivers/clk/meson/clk-phase.h26
-rw-r--r--drivers/clk/meson/clk-pll.c216
-rw-r--r--drivers/clk/meson/clk-pll.h49
-rw-r--r--drivers/clk/meson/clk-regmap.c5
-rw-r--r--drivers/clk/meson/clk-regmap.h20
-rw-r--r--drivers/clk/meson/clk-triphase.c68
-rw-r--r--drivers/clk/meson/clkc.h127
-rw-r--r--drivers/clk/meson/g12a-aoclk.c454
-rw-r--r--drivers/clk/meson/g12a-aoclk.h34
-rw-r--r--drivers/clk/meson/g12a.c2359
-rw-r--r--drivers/clk/meson/g12a.h175
-rw-r--r--drivers/clk/meson/gxbb-aoclk-32k.c193
-rw-r--r--drivers/clk/meson/gxbb-aoclk.c268
-rw-r--r--drivers/clk/meson/gxbb-aoclk.h20
-rw-r--r--drivers/clk/meson/gxbb.c296
-rw-r--r--drivers/clk/meson/meson-aoclk.c54
-rw-r--r--drivers/clk/meson/meson-aoclk.h13
-rw-r--r--drivers/clk/meson/meson-eeclk.c63
-rw-r--r--drivers/clk/meson/meson-eeclk.h25
-rw-r--r--drivers/clk/meson/meson8b.c374
-rw-r--r--drivers/clk/meson/meson8b.h11
-rw-r--r--drivers/clk/meson/parm.h46
-rw-r--r--drivers/clk/meson/sclk-div.c10
-rw-r--r--drivers/clk/meson/sclk-div.h (renamed from drivers/clk/meson/clkc-audio.h)16
-rw-r--r--drivers/clk/meson/vid-pll-div.c10
-rw-r--r--drivers/clk/meson/vid-pll-div.h20
39 files changed, 4921 insertions, 755 deletions
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index efaa70f682b4..3858747f5438 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -1,27 +1,52 @@
1config COMMON_CLK_AMLOGIC 1config COMMON_CLK_MESON_INPUT
2 bool 2 tristate
3 depends on ARCH_MESON || COMPILE_TEST
4 select COMMON_CLK_REGMAP_MESON
5 3
6config COMMON_CLK_AMLOGIC_AUDIO 4config COMMON_CLK_MESON_REGMAP
7 bool 5 tristate
8 depends on ARCH_MESON || COMPILE_TEST 6 select REGMAP
9 select COMMON_CLK_AMLOGIC
10 7
11config COMMON_CLK_MESON_AO 8config COMMON_CLK_MESON_DUALDIV
12 bool 9 tristate
13 depends on OF 10 select COMMON_CLK_MESON_REGMAP
14 depends on ARCH_MESON || COMPILE_TEST 11
15 select COMMON_CLK_REGMAP_MESON 12config COMMON_CLK_MESON_MPLL
13 tristate
14 select COMMON_CLK_MESON_REGMAP
15
16config COMMON_CLK_MESON_PHASE
17 tristate
18 select COMMON_CLK_MESON_REGMAP
19
20config COMMON_CLK_MESON_PLL
21 tristate
22 select COMMON_CLK_MESON_REGMAP
23
24config COMMON_CLK_MESON_SCLK_DIV
25 tristate
26 select COMMON_CLK_MESON_REGMAP
27
28config COMMON_CLK_MESON_VID_PLL_DIV
29 tristate
30 select COMMON_CLK_MESON_REGMAP
31
32config COMMON_CLK_MESON_AO_CLKC
33 tristate
34 select COMMON_CLK_MESON_REGMAP
35 select COMMON_CLK_MESON_INPUT
16 select RESET_CONTROLLER 36 select RESET_CONTROLLER
17 37
18config COMMON_CLK_REGMAP_MESON 38config COMMON_CLK_MESON_EE_CLKC
19 bool 39 tristate
20 select REGMAP 40 select COMMON_CLK_MESON_REGMAP
41 select COMMON_CLK_MESON_INPUT
21 42
22config COMMON_CLK_MESON8B 43config COMMON_CLK_MESON8B
23 bool 44 bool
24 select COMMON_CLK_AMLOGIC 45 depends on ARCH_MESON
46 select COMMON_CLK_MESON_REGMAP
47 select COMMON_CLK_MESON_MPLL
48 select COMMON_CLK_MESON_PLL
49 select MFD_SYSCON
25 select RESET_CONTROLLER 50 select RESET_CONTROLLER
26 help 51 help
27 Support for the clock controller on AmLogic S802 (Meson8), 52 Support for the clock controller on AmLogic S802 (Meson8),
@@ -30,8 +55,14 @@ config COMMON_CLK_MESON8B
30 55
31config COMMON_CLK_GXBB 56config COMMON_CLK_GXBB
32 bool 57 bool
33 select COMMON_CLK_AMLOGIC 58 depends on ARCH_MESON
34 select COMMON_CLK_MESON_AO 59 select COMMON_CLK_MESON_REGMAP
60 select COMMON_CLK_MESON_DUALDIV
61 select COMMON_CLK_MESON_VID_PLL_DIV
62 select COMMON_CLK_MESON_MPLL
63 select COMMON_CLK_MESON_PLL
64 select COMMON_CLK_MESON_AO_CLKC
65 select COMMON_CLK_MESON_EE_CLKC
35 select MFD_SYSCON 66 select MFD_SYSCON
36 help 67 help
37 Support for the clock controller on AmLogic S905 devices, aka gxbb. 68 Support for the clock controller on AmLogic S905 devices, aka gxbb.
@@ -39,8 +70,13 @@ config COMMON_CLK_GXBB
39 70
40config COMMON_CLK_AXG 71config COMMON_CLK_AXG
41 bool 72 bool
42 select COMMON_CLK_AMLOGIC 73 depends on ARCH_MESON
43 select COMMON_CLK_MESON_AO 74 select COMMON_CLK_MESON_REGMAP
75 select COMMON_CLK_MESON_DUALDIV
76 select COMMON_CLK_MESON_MPLL
77 select COMMON_CLK_MESON_PLL
78 select COMMON_CLK_MESON_AO_CLKC
79 select COMMON_CLK_MESON_EE_CLKC
44 select MFD_SYSCON 80 select MFD_SYSCON
45 help 81 help
46 Support for the clock controller on AmLogic A113D devices, aka axg. 82 Support for the clock controller on AmLogic A113D devices, aka axg.
@@ -48,9 +84,26 @@ config COMMON_CLK_AXG
48 84
49config COMMON_CLK_AXG_AUDIO 85config COMMON_CLK_AXG_AUDIO
50 tristate "Meson AXG Audio Clock Controller Driver" 86 tristate "Meson AXG Audio Clock Controller Driver"
51 depends on COMMON_CLK_AXG 87 depends on ARCH_MESON
52 select COMMON_CLK_AMLOGIC_AUDIO 88 select COMMON_CLK_MESON_INPUT
53 select MFD_SYSCON 89 select COMMON_CLK_MESON_REGMAP
90 select COMMON_CLK_MESON_PHASE
91 select COMMON_CLK_MESON_SCLK_DIV
92 select REGMAP_MMIO
54 help 93 help
55 Support for the audio clock controller on AmLogic A113D devices, 94 Support for the audio clock controller on AmLogic A113D devices,
56 aka axg, Say Y if you want audio subsystem to work. 95 aka axg, Say Y if you want audio subsystem to work.
96
97config COMMON_CLK_G12A
98 bool
99 depends on ARCH_MESON
100 select COMMON_CLK_MESON_REGMAP
101 select COMMON_CLK_MESON_DUALDIV
102 select COMMON_CLK_MESON_MPLL
103 select COMMON_CLK_MESON_PLL
104 select COMMON_CLK_MESON_AO_CLKC
105 select COMMON_CLK_MESON_EE_CLKC
106 select MFD_SYSCON
107 help
108 Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
109 devices, aka g12a. Say Y if you want peripherals to work.
diff --git a/drivers/clk/meson/Makefile b/drivers/clk/meson/Makefile
index a849aa809825..021fc290e749 100644
--- a/drivers/clk/meson/Makefile
+++ b/drivers/clk/meson/Makefile
@@ -1,13 +1,20 @@
1# 1# Amlogic clock drivers
2# Makefile for Meson specific clk
3#
4 2
5obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o 3obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o
6obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-input.o 4obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o
7obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO) += clk-triphase.o sclk-div.o 5obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
8obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o 6obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o
7obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
8obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
9obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o
10obj-$(CONFIG_COMMON_CLK_MESON_REGMAP) += clk-regmap.o
11obj-$(CONFIG_COMMON_CLK_MESON_SCLK_DIV) += sclk-div.o
12obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
13
14# Amlogic Clock controllers
15
16obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
17obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
18obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
19obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
9obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o 20obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
10obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
11obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
12obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
13obj-$(CONFIG_COMMON_CLK_REGMAP_MESON) += clk-regmap.o
diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c
index 29e088542387..0086f31288eb 100644
--- a/drivers/clk/meson/axg-aoclk.c
+++ b/drivers/clk/meson/axg-aoclk.c
@@ -12,10 +12,27 @@
12#include <linux/platform_device.h> 12#include <linux/platform_device.h>
13#include <linux/reset-controller.h> 13#include <linux/reset-controller.h>
14#include <linux/mfd/syscon.h> 14#include <linux/mfd/syscon.h>
15#include "clk-regmap.h"
16#include "meson-aoclk.h" 15#include "meson-aoclk.h"
17#include "axg-aoclk.h" 16#include "axg-aoclk.h"
18 17
18#include "clk-regmap.h"
19#include "clk-dualdiv.h"
20
21#define IN_PREFIX "ao-in-"
22
23/*
24 * AO Configuration Clock registers offsets
25 * Register offsets from the data sheet must be multiplied by 4.
26 */
27#define AO_RTI_PWR_CNTL_REG1 0x0C
28#define AO_RTI_PWR_CNTL_REG0 0x10
29#define AO_RTI_GEN_CNTL_REG0 0x40
30#define AO_OSCIN_CNTL 0x58
31#define AO_CRT_CLK_CNTL1 0x68
32#define AO_SAR_CLK 0x90
33#define AO_RTC_ALT_CLK_CNTL0 0x94
34#define AO_RTC_ALT_CLK_CNTL1 0x98
35
19#define AXG_AO_GATE(_name, _bit) \ 36#define AXG_AO_GATE(_name, _bit) \
20static struct clk_regmap axg_aoclk_##_name = { \ 37static struct clk_regmap axg_aoclk_##_name = { \
21 .data = &(struct clk_regmap_gate_data) { \ 38 .data = &(struct clk_regmap_gate_data) { \
@@ -25,7 +42,7 @@ static struct clk_regmap axg_aoclk_##_name = { \
25 .hw.init = &(struct clk_init_data) { \ 42 .hw.init = &(struct clk_init_data) { \
26 .name = "axg_ao_" #_name, \ 43 .name = "axg_ao_" #_name, \
27 .ops = &clk_regmap_gate_ops, \ 44 .ops = &clk_regmap_gate_ops, \
28 .parent_names = (const char *[]){ "clk81" }, \ 45 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
29 .num_parents = 1, \ 46 .num_parents = 1, \
30 .flags = CLK_IGNORE_UNUSED, \ 47 .flags = CLK_IGNORE_UNUSED, \
31 }, \ 48 }, \
@@ -39,17 +56,141 @@ AXG_AO_GATE(uart2, 5);
39AXG_AO_GATE(ir_blaster, 6); 56AXG_AO_GATE(ir_blaster, 6);
40AXG_AO_GATE(saradc, 7); 57AXG_AO_GATE(saradc, 7);
41 58
59static struct clk_regmap axg_aoclk_cts_oscin = {
60 .data = &(struct clk_regmap_gate_data){
61 .offset = AO_RTI_PWR_CNTL_REG0,
62 .bit_idx = 14,
63 },
64 .hw.init = &(struct clk_init_data){
65 .name = "cts_oscin",
66 .ops = &clk_regmap_gate_ro_ops,
67 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
68 .num_parents = 1,
69 },
70};
71
72static struct clk_regmap axg_aoclk_32k_pre = {
73 .data = &(struct clk_regmap_gate_data){
74 .offset = AO_RTC_ALT_CLK_CNTL0,
75 .bit_idx = 31,
76 },
77 .hw.init = &(struct clk_init_data){
78 .name = "axg_ao_32k_pre",
79 .ops = &clk_regmap_gate_ops,
80 .parent_names = (const char *[]){ "cts_oscin" },
81 .num_parents = 1,
82 },
83};
84
85static const struct meson_clk_dualdiv_param axg_32k_div_table[] = {
86 {
87 .dual = 1,
88 .n1 = 733,
89 .m1 = 8,
90 .n2 = 732,
91 .m2 = 11,
92 }, {}
93};
94
95static struct clk_regmap axg_aoclk_32k_div = {
96 .data = &(struct meson_clk_dualdiv_data){
97 .n1 = {
98 .reg_off = AO_RTC_ALT_CLK_CNTL0,
99 .shift = 0,
100 .width = 12,
101 },
102 .n2 = {
103 .reg_off = AO_RTC_ALT_CLK_CNTL0,
104 .shift = 12,
105 .width = 12,
106 },
107 .m1 = {
108 .reg_off = AO_RTC_ALT_CLK_CNTL1,
109 .shift = 0,
110 .width = 12,
111 },
112 .m2 = {
113 .reg_off = AO_RTC_ALT_CLK_CNTL1,
114 .shift = 12,
115 .width = 12,
116 },
117 .dual = {
118 .reg_off = AO_RTC_ALT_CLK_CNTL0,
119 .shift = 28,
120 .width = 1,
121 },
122 .table = axg_32k_div_table,
123 },
124 .hw.init = &(struct clk_init_data){
125 .name = "axg_ao_32k_div",
126 .ops = &meson_clk_dualdiv_ops,
127 .parent_names = (const char *[]){ "axg_ao_32k_pre" },
128 .num_parents = 1,
129 },
130};
131
132static struct clk_regmap axg_aoclk_32k_sel = {
133 .data = &(struct clk_regmap_mux_data) {
134 .offset = AO_RTC_ALT_CLK_CNTL1,
135 .mask = 0x1,
136 .shift = 24,
137 .flags = CLK_MUX_ROUND_CLOSEST,
138 },
139 .hw.init = &(struct clk_init_data){
140 .name = "axg_ao_32k_sel",
141 .ops = &clk_regmap_mux_ops,
142 .parent_names = (const char *[]){ "axg_ao_32k_div",
143 "axg_ao_32k_pre" },
144 .num_parents = 2,
145 .flags = CLK_SET_RATE_PARENT,
146 },
147};
148
149static struct clk_regmap axg_aoclk_32k = {
150 .data = &(struct clk_regmap_gate_data){
151 .offset = AO_RTC_ALT_CLK_CNTL0,
152 .bit_idx = 30,
153 },
154 .hw.init = &(struct clk_init_data){
155 .name = "axg_ao_32k",
156 .ops = &clk_regmap_gate_ops,
157 .parent_names = (const char *[]){ "axg_ao_32k_sel" },
158 .num_parents = 1,
159 .flags = CLK_SET_RATE_PARENT,
160 },
161};
162
163static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
164 .data = &(struct clk_regmap_mux_data) {
165 .offset = AO_RTI_PWR_CNTL_REG0,
166 .mask = 0x1,
167 .shift = 10,
168 .flags = CLK_MUX_ROUND_CLOSEST,
169 },
170 .hw.init = &(struct clk_init_data){
171 .name = "axg_ao_cts_rtc_oscin",
172 .ops = &clk_regmap_mux_ops,
173 .parent_names = (const char *[]){ "axg_ao_32k",
174 IN_PREFIX "ext_32k-0" },
175 .num_parents = 2,
176 .flags = CLK_SET_RATE_PARENT,
177 },
178};
179
42static struct clk_regmap axg_aoclk_clk81 = { 180static struct clk_regmap axg_aoclk_clk81 = {
43 .data = &(struct clk_regmap_mux_data) { 181 .data = &(struct clk_regmap_mux_data) {
44 .offset = AO_RTI_PWR_CNTL_REG0, 182 .offset = AO_RTI_PWR_CNTL_REG0,
45 .mask = 0x1, 183 .mask = 0x1,
46 .shift = 8, 184 .shift = 8,
185 .flags = CLK_MUX_ROUND_CLOSEST,
47 }, 186 },
48 .hw.init = &(struct clk_init_data){ 187 .hw.init = &(struct clk_init_data){
49 .name = "axg_ao_clk81", 188 .name = "axg_ao_clk81",
50 .ops = &clk_regmap_mux_ro_ops, 189 .ops = &clk_regmap_mux_ro_ops,
51 .parent_names = (const char *[]){ "clk81", "ao_alt_xtal"}, 190 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
191 "axg_ao_cts_rtc_oscin"},
52 .num_parents = 2, 192 .num_parents = 2,
193 .flags = CLK_SET_RATE_PARENT,
53 }, 194 },
54}; 195};
55 196
@@ -62,7 +203,8 @@ static struct clk_regmap axg_aoclk_saradc_mux = {
62 .hw.init = &(struct clk_init_data){ 203 .hw.init = &(struct clk_init_data){
63 .name = "axg_ao_saradc_mux", 204 .name = "axg_ao_saradc_mux",
64 .ops = &clk_regmap_mux_ops, 205 .ops = &clk_regmap_mux_ops,
65 .parent_names = (const char *[]){ "xtal", "axg_ao_clk81" }, 206 .parent_names = (const char *[]){ IN_PREFIX "xtal",
207 "axg_ao_clk81" },
66 .num_parents = 2, 208 .num_parents = 2,
67 }, 209 },
68}; 210};
@@ -106,17 +248,23 @@ static const unsigned int axg_aoclk_reset[] = {
106}; 248};
107 249
108static struct clk_regmap *axg_aoclk_regmap[] = { 250static struct clk_regmap *axg_aoclk_regmap[] = {
109 [CLKID_AO_REMOTE] = &axg_aoclk_remote, 251 &axg_aoclk_remote,
110 [CLKID_AO_I2C_MASTER] = &axg_aoclk_i2c_master, 252 &axg_aoclk_i2c_master,
111 [CLKID_AO_I2C_SLAVE] = &axg_aoclk_i2c_slave, 253 &axg_aoclk_i2c_slave,
112 [CLKID_AO_UART1] = &axg_aoclk_uart1, 254 &axg_aoclk_uart1,
113 [CLKID_AO_UART2] = &axg_aoclk_uart2, 255 &axg_aoclk_uart2,
114 [CLKID_AO_IR_BLASTER] = &axg_aoclk_ir_blaster, 256 &axg_aoclk_ir_blaster,
115 [CLKID_AO_SAR_ADC] = &axg_aoclk_saradc, 257 &axg_aoclk_saradc,
116 [CLKID_AO_CLK81] = &axg_aoclk_clk81, 258 &axg_aoclk_cts_oscin,
117 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux, 259 &axg_aoclk_32k_pre,
118 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div, 260 &axg_aoclk_32k_div,
119 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate, 261 &axg_aoclk_32k_sel,
262 &axg_aoclk_32k,
263 &axg_aoclk_cts_rtc_oscin,
264 &axg_aoclk_clk81,
265 &axg_aoclk_saradc_mux,
266 &axg_aoclk_saradc_div,
267 &axg_aoclk_saradc_gate,
120}; 268};
121 269
122static const struct clk_hw_onecell_data axg_aoclk_onecell_data = { 270static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
@@ -132,10 +280,22 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
132 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux.hw, 280 [CLKID_AO_SAR_ADC_SEL] = &axg_aoclk_saradc_mux.hw,
133 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div.hw, 281 [CLKID_AO_SAR_ADC_DIV] = &axg_aoclk_saradc_div.hw,
134 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate.hw, 282 [CLKID_AO_SAR_ADC_CLK] = &axg_aoclk_saradc_gate.hw,
283 [CLKID_AO_CTS_OSCIN] = &axg_aoclk_cts_oscin.hw,
284 [CLKID_AO_32K_PRE] = &axg_aoclk_32k_pre.hw,
285 [CLKID_AO_32K_DIV] = &axg_aoclk_32k_div.hw,
286 [CLKID_AO_32K_SEL] = &axg_aoclk_32k_sel.hw,
287 [CLKID_AO_32K] = &axg_aoclk_32k.hw,
288 [CLKID_AO_CTS_RTC_OSCIN] = &axg_aoclk_cts_rtc_oscin.hw,
135 }, 289 },
136 .num = NR_CLKS, 290 .num = NR_CLKS,
137}; 291};
138 292
293static const struct meson_aoclk_input axg_aoclk_inputs[] = {
294 { .name = "xtal", .required = true },
295 { .name = "mpeg-clk", .required = true },
296 { .name = "ext-32k-0", .required = false },
297};
298
139static const struct meson_aoclk_data axg_aoclkc_data = { 299static const struct meson_aoclk_data axg_aoclkc_data = {
140 .reset_reg = AO_RTI_GEN_CNTL_REG0, 300 .reset_reg = AO_RTI_GEN_CNTL_REG0,
141 .num_reset = ARRAY_SIZE(axg_aoclk_reset), 301 .num_reset = ARRAY_SIZE(axg_aoclk_reset),
@@ -143,6 +303,9 @@ static const struct meson_aoclk_data axg_aoclkc_data = {
143 .num_clks = ARRAY_SIZE(axg_aoclk_regmap), 303 .num_clks = ARRAY_SIZE(axg_aoclk_regmap),
144 .clks = axg_aoclk_regmap, 304 .clks = axg_aoclk_regmap,
145 .hw_data = &axg_aoclk_onecell_data, 305 .hw_data = &axg_aoclk_onecell_data,
306 .inputs = axg_aoclk_inputs,
307 .num_inputs = ARRAY_SIZE(axg_aoclk_inputs),
308 .input_prefix = IN_PREFIX,
146}; 309};
147 310
148static const struct of_device_id axg_aoclkc_match_table[] = { 311static const struct of_device_id axg_aoclkc_match_table[] = {
diff --git a/drivers/clk/meson/axg-aoclk.h b/drivers/clk/meson/axg-aoclk.h
index 91384d8dd844..3cc27e85170f 100644
--- a/drivers/clk/meson/axg-aoclk.h
+++ b/drivers/clk/meson/axg-aoclk.h
@@ -10,18 +10,7 @@
10#ifndef __AXG_AOCLKC_H 10#ifndef __AXG_AOCLKC_H
11#define __AXG_AOCLKC_H 11#define __AXG_AOCLKC_H
12 12
13#define NR_CLKS 11 13#define NR_CLKS 17
14/* AO Configuration Clock registers offsets
15 * Register offsets from the data sheet must be multiplied by 4.
16 */
17#define AO_RTI_PWR_CNTL_REG1 0x0C
18#define AO_RTI_PWR_CNTL_REG0 0x10
19#define AO_RTI_GEN_CNTL_REG0 0x40
20#define AO_OSCIN_CNTL 0x58
21#define AO_CRT_CLK_CNTL1 0x68
22#define AO_SAR_CLK 0x90
23#define AO_RTC_ALT_CLK_CNTL0 0x94
24#define AO_RTC_ALT_CLK_CNTL1 0x98
25 14
26#include <dt-bindings/clock/axg-aoclkc.h> 15#include <dt-bindings/clock/axg-aoclkc.h>
27#include <dt-bindings/reset/axg-aoclkc.h> 16#include <dt-bindings/reset/axg-aoclkc.h>
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 8ac3a2295473..7ab200b6c3bf 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -14,8 +14,11 @@
14#include <linux/reset.h> 14#include <linux/reset.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16 16
17#include "clkc-audio.h"
18#include "axg-audio.h" 17#include "axg-audio.h"
18#include "clk-input.h"
19#include "clk-regmap.h"
20#include "clk-phase.h"
21#include "sclk-div.h"
19 22
20#define AXG_MST_IN_COUNT 8 23#define AXG_MST_IN_COUNT 8
21#define AXG_SLV_SCLK_COUNT 10 24#define AXG_SLV_SCLK_COUNT 10
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 792735d7e46e..7a8ef80e5f2c 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -9,16 +9,17 @@
9 * Author: Qiufang Dai <qiufang.dai@amlogic.com> 9 * Author: Qiufang Dai <qiufang.dai@amlogic.com>
10 */ 10 */
11 11
12#include <linux/clk.h>
13#include <linux/clk-provider.h> 12#include <linux/clk-provider.h>
14#include <linux/init.h> 13#include <linux/init.h>
15#include <linux/of_device.h> 14#include <linux/of_device.h>
16#include <linux/mfd/syscon.h>
17#include <linux/platform_device.h> 15#include <linux/platform_device.h>
18#include <linux/regmap.h>
19 16
20#include "clkc.h" 17#include "clk-input.h"
18#include "clk-regmap.h"
19#include "clk-pll.h"
20#include "clk-mpll.h"
21#include "axg.h" 21#include "axg.h"
22#include "meson-eeclk.h"
22 23
23static DEFINE_SPINLOCK(meson_clk_lock); 24static DEFINE_SPINLOCK(meson_clk_lock);
24 25
@@ -58,7 +59,7 @@ static struct clk_regmap axg_fixed_pll_dco = {
58 .hw.init = &(struct clk_init_data){ 59 .hw.init = &(struct clk_init_data){
59 .name = "fixed_pll_dco", 60 .name = "fixed_pll_dco",
60 .ops = &meson_clk_pll_ro_ops, 61 .ops = &meson_clk_pll_ro_ops,
61 .parent_names = (const char *[]){ "xtal" }, 62 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
62 .num_parents = 1, 63 .num_parents = 1,
63 }, 64 },
64}; 65};
@@ -113,7 +114,7 @@ static struct clk_regmap axg_sys_pll_dco = {
113 .hw.init = &(struct clk_init_data){ 114 .hw.init = &(struct clk_init_data){
114 .name = "sys_pll_dco", 115 .name = "sys_pll_dco",
115 .ops = &meson_clk_pll_ro_ops, 116 .ops = &meson_clk_pll_ro_ops,
116 .parent_names = (const char *[]){ "xtal" }, 117 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
117 .num_parents = 1, 118 .num_parents = 1,
118 }, 119 },
119}; 120};
@@ -214,7 +215,7 @@ static struct clk_regmap axg_gp0_pll_dco = {
214 .hw.init = &(struct clk_init_data){ 215 .hw.init = &(struct clk_init_data){
215 .name = "gp0_pll_dco", 216 .name = "gp0_pll_dco",
216 .ops = &meson_clk_pll_ops, 217 .ops = &meson_clk_pll_ops,
217 .parent_names = (const char *[]){ "xtal" }, 218 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
218 .num_parents = 1, 219 .num_parents = 1,
219 }, 220 },
220}; 221};
@@ -283,7 +284,7 @@ static struct clk_regmap axg_hifi_pll_dco = {
283 .hw.init = &(struct clk_init_data){ 284 .hw.init = &(struct clk_init_data){
284 .name = "hifi_pll_dco", 285 .name = "hifi_pll_dco",
285 .ops = &meson_clk_pll_ops, 286 .ops = &meson_clk_pll_ops,
286 .parent_names = (const char *[]){ "xtal" }, 287 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
287 .num_parents = 1, 288 .num_parents = 1,
288 }, 289 },
289}; 290};
@@ -701,7 +702,7 @@ static struct clk_regmap axg_pcie_pll_dco = {
701 .hw.init = &(struct clk_init_data){ 702 .hw.init = &(struct clk_init_data){
702 .name = "pcie_pll_dco", 703 .name = "pcie_pll_dco",
703 .ops = &meson_clk_pll_ops, 704 .ops = &meson_clk_pll_ops,
704 .parent_names = (const char *[]){ "xtal" }, 705 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
705 .num_parents = 1, 706 .num_parents = 1,
706 }, 707 },
707}; 708};
@@ -803,7 +804,7 @@ static struct clk_regmap axg_pcie_cml_en1 = {
803 804
804static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; 805static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
805static const char * const clk81_parent_names[] = { 806static const char * const clk81_parent_names[] = {
806 "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", 807 IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
807 "fclk_div3", "fclk_div5" 808 "fclk_div3", "fclk_div5"
808}; 809};
809 810
@@ -852,7 +853,7 @@ static struct clk_regmap axg_clk81 = {
852}; 853};
853 854
854static const char * const axg_sd_emmc_clk0_parent_names[] = { 855static const char * const axg_sd_emmc_clk0_parent_names[] = {
855 "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", 856 IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
856 857
857 /* 858 /*
858 * Following these parent clocks, we should also have had mpll2, mpll3 859 * Following these parent clocks, we should also have had mpll2, mpll3
@@ -957,7 +958,7 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
957static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8, 958static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
958 9, 10, 11, 13, 14, }; 959 9, 10, 11, 13, 14, };
959static const char * const gen_clk_parent_names[] = { 960static const char * const gen_clk_parent_names[] = {
960 "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3", 961 IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
961 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll", 962 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
962}; 963};
963 964
@@ -1255,46 +1256,20 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
1255 &axg_pcie_pll_od, 1256 &axg_pcie_pll_od,
1256}; 1257};
1257 1258
1259static const struct meson_eeclkc_data axg_clkc_data = {
1260 .regmap_clks = axg_clk_regmaps,
1261 .regmap_clk_num = ARRAY_SIZE(axg_clk_regmaps),
1262 .hw_onecell_data = &axg_hw_onecell_data,
1263};
1264
1265
1258static const struct of_device_id clkc_match_table[] = { 1266static const struct of_device_id clkc_match_table[] = {
1259 { .compatible = "amlogic,axg-clkc" }, 1267 { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
1260 {} 1268 {}
1261}; 1269};
1262 1270
1263static int axg_clkc_probe(struct platform_device *pdev)
1264{
1265 struct device *dev = &pdev->dev;
1266 struct regmap *map;
1267 int ret, i;
1268
1269 /* Get the hhi system controller node if available */
1270 map = syscon_node_to_regmap(of_get_parent(dev->of_node));
1271 if (IS_ERR(map)) {
1272 dev_err(dev, "failed to get HHI regmap\n");
1273 return PTR_ERR(map);
1274 }
1275
1276 /* Populate regmap for the regmap backed clocks */
1277 for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
1278 axg_clk_regmaps[i]->map = map;
1279
1280 for (i = 0; i < axg_hw_onecell_data.num; i++) {
1281 /* array might be sparse */
1282 if (!axg_hw_onecell_data.hws[i])
1283 continue;
1284
1285 ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
1286 if (ret) {
1287 dev_err(dev, "Clock registration failed\n");
1288 return ret;
1289 }
1290 }
1291
1292 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
1293 &axg_hw_onecell_data);
1294}
1295
1296static struct platform_driver axg_driver = { 1271static struct platform_driver axg_driver = {
1297 .probe = axg_clkc_probe, 1272 .probe = meson_eeclkc_probe,
1298 .driver = { 1273 .driver = {
1299 .name = "axg-clkc", 1274 .name = "axg-clkc",
1300 .of_match_table = clkc_match_table, 1275 .of_match_table = clkc_match_table,
diff --git a/drivers/clk/meson/clk-dualdiv.c b/drivers/clk/meson/clk-dualdiv.c
new file mode 100644
index 000000000000..c5ca23a5e3e8
--- /dev/null
+++ b/drivers/clk/meson/clk-dualdiv.c
@@ -0,0 +1,138 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2017 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 * Author: Jerome Brunet <jbrunet@baylibre.com>
6 */
7
8/*
9 * The AO Domain embeds a dual/divider to generate a more precise
10 * 32,768KHz clock for low-power suspend mode and CEC.
11 * ______ ______
12 * | | | |
13 * | Div1 |-| Cnt1 |
14 * /|______| |______|\
15 * -| ______ ______ X--> Out
16 * \| | | |/
17 * | Div2 |-| Cnt2 |
18 * |______| |______|
19 *
20 * The dividing can be switched to single or dual, with a counter
21 * for each divider to set when the switching is done.
22 */
23
24#include <linux/clk-provider.h>
25#include <linux/module.h>
26
27#include "clk-regmap.h"
28#include "clk-dualdiv.h"
29
30static inline struct meson_clk_dualdiv_data *
31meson_clk_dualdiv_data(struct clk_regmap *clk)
32{
33 return (struct meson_clk_dualdiv_data *)clk->data;
34}
35
36static unsigned long
37__dualdiv_param_to_rate(unsigned long parent_rate,
38 const struct meson_clk_dualdiv_param *p)
39{
40 if (!p->dual)
41 return DIV_ROUND_CLOSEST(parent_rate, p->n1);
42
43 return DIV_ROUND_CLOSEST(parent_rate * (p->m1 + p->m2),
44 p->n1 * p->m1 + p->n2 * p->m2);
45}
46
47static unsigned long meson_clk_dualdiv_recalc_rate(struct clk_hw *hw,
48 unsigned long parent_rate)
49{
50 struct clk_regmap *clk = to_clk_regmap(hw);
51 struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
52 struct meson_clk_dualdiv_param setting;
53
54 setting.dual = meson_parm_read(clk->map, &dualdiv->dual);
55 setting.n1 = meson_parm_read(clk->map, &dualdiv->n1) + 1;
56 setting.m1 = meson_parm_read(clk->map, &dualdiv->m1) + 1;
57 setting.n2 = meson_parm_read(clk->map, &dualdiv->n2) + 1;
58 setting.m2 = meson_parm_read(clk->map, &dualdiv->m2) + 1;
59
60 return __dualdiv_param_to_rate(parent_rate, &setting);
61}
62
63static const struct meson_clk_dualdiv_param *
64__dualdiv_get_setting(unsigned long rate, unsigned long parent_rate,
65 struct meson_clk_dualdiv_data *dualdiv)
66{
67 const struct meson_clk_dualdiv_param *table = dualdiv->table;
68 unsigned long best = 0, now = 0;
69 unsigned int i, best_i = 0;
70
71 if (!table)
72 return NULL;
73
74 for (i = 0; table[i].n1; i++) {
75 now = __dualdiv_param_to_rate(parent_rate, &table[i]);
76
77 /* If we get an exact match, don't bother any further */
78 if (now == rate) {
79 return &table[i];
80 } else if (abs(now - rate) < abs(best - rate)) {
81 best = now;
82 best_i = i;
83 }
84 }
85
86 return (struct meson_clk_dualdiv_param *)&table[best_i];
87}
88
89static long meson_clk_dualdiv_round_rate(struct clk_hw *hw, unsigned long rate,
90 unsigned long *parent_rate)
91{
92 struct clk_regmap *clk = to_clk_regmap(hw);
93 struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
94 const struct meson_clk_dualdiv_param *setting =
95 __dualdiv_get_setting(rate, *parent_rate, dualdiv);
96
97 if (!setting)
98 return meson_clk_dualdiv_recalc_rate(hw, *parent_rate);
99
100 return __dualdiv_param_to_rate(*parent_rate, setting);
101}
102
103static int meson_clk_dualdiv_set_rate(struct clk_hw *hw, unsigned long rate,
104 unsigned long parent_rate)
105{
106 struct clk_regmap *clk = to_clk_regmap(hw);
107 struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
108 const struct meson_clk_dualdiv_param *setting =
109 __dualdiv_get_setting(rate, parent_rate, dualdiv);
110
111 if (!setting)
112 return -EINVAL;
113
114 meson_parm_write(clk->map, &dualdiv->dual, setting->dual);
115 meson_parm_write(clk->map, &dualdiv->n1, setting->n1 - 1);
116 meson_parm_write(clk->map, &dualdiv->m1, setting->m1 - 1);
117 meson_parm_write(clk->map, &dualdiv->n2, setting->n2 - 1);
118 meson_parm_write(clk->map, &dualdiv->m2, setting->m2 - 1);
119
120 return 0;
121}
122
123const struct clk_ops meson_clk_dualdiv_ops = {
124 .recalc_rate = meson_clk_dualdiv_recalc_rate,
125 .round_rate = meson_clk_dualdiv_round_rate,
126 .set_rate = meson_clk_dualdiv_set_rate,
127};
128EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ops);
129
130const struct clk_ops meson_clk_dualdiv_ro_ops = {
131 .recalc_rate = meson_clk_dualdiv_recalc_rate,
132};
133EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ro_ops);
134
135MODULE_DESCRIPTION("Amlogic dual divider driver");
136MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
137MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
138MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-dualdiv.h b/drivers/clk/meson/clk-dualdiv.h
new file mode 100644
index 000000000000..4aa939018012
--- /dev/null
+++ b/drivers/clk/meson/clk-dualdiv.h
@@ -0,0 +1,33 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLK_DUALDIV_H
8#define __MESON_CLK_DUALDIV_H
9
10#include <linux/clk-provider.h>
11#include "parm.h"
12
13struct meson_clk_dualdiv_param {
14 unsigned int n1;
15 unsigned int n2;
16 unsigned int m1;
17 unsigned int m2;
18 unsigned int dual;
19};
20
21struct meson_clk_dualdiv_data {
22 struct parm n1;
23 struct parm n2;
24 struct parm m1;
25 struct parm m2;
26 struct parm dual;
27 const struct meson_clk_dualdiv_param *table;
28};
29
30extern const struct clk_ops meson_clk_dualdiv_ops;
31extern const struct clk_ops meson_clk_dualdiv_ro_ops;
32
33#endif /* __MESON_CLK_DUALDIV_H */
diff --git a/drivers/clk/meson/clk-input.c b/drivers/clk/meson/clk-input.c
index 06b3e3bb6a66..086226e9dba6 100644
--- a/drivers/clk/meson/clk-input.c
+++ b/drivers/clk/meson/clk-input.c
@@ -7,7 +7,8 @@
7#include <linux/clk.h> 7#include <linux/clk.h>
8#include <linux/clk-provider.h> 8#include <linux/clk-provider.h>
9#include <linux/device.h> 9#include <linux/device.h>
10#include "clkc.h" 10#include <linux/module.h>
11#include "clk-input.h"
11 12
12static const struct clk_ops meson_clk_no_ops = {}; 13static const struct clk_ops meson_clk_no_ops = {};
13 14
@@ -42,3 +43,7 @@ struct clk_hw *meson_clk_hw_register_input(struct device *dev,
42 return ret ? ERR_PTR(ret) : hw; 43 return ret ? ERR_PTR(ret) : hw;
43} 44}
44EXPORT_SYMBOL_GPL(meson_clk_hw_register_input); 45EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
46
47MODULE_DESCRIPTION("Amlogic clock input helper");
48MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
49MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-input.h b/drivers/clk/meson/clk-input.h
new file mode 100644
index 000000000000..4a541b9685a6
--- /dev/null
+++ b/drivers/clk/meson/clk-input.h
@@ -0,0 +1,19 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLK_INPUT_H
8#define __MESON_CLK_INPUT_H
9
10#include <linux/clk-provider.h>
11
12struct device;
13
14struct clk_hw *meson_clk_hw_register_input(struct device *dev,
15 const char *of_name,
16 const char *clk_name,
17 unsigned long flags);
18
19#endif /* __MESON_CLK_INPUT_H */
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index 650f75cc15a9..f76850d99e59 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -12,7 +12,11 @@
12 */ 12 */
13 13
14#include <linux/clk-provider.h> 14#include <linux/clk-provider.h>
15#include "clkc.h" 15#include <linux/module.h>
16#include <linux/spinlock.h>
17
18#include "clk-regmap.h"
19#include "clk-mpll.h"
16 20
17#define SDM_DEN 16384 21#define SDM_DEN 16384
18#define N2_MIN 4 22#define N2_MIN 4
@@ -138,9 +142,15 @@ const struct clk_ops meson_clk_mpll_ro_ops = {
138 .recalc_rate = mpll_recalc_rate, 142 .recalc_rate = mpll_recalc_rate,
139 .round_rate = mpll_round_rate, 143 .round_rate = mpll_round_rate,
140}; 144};
145EXPORT_SYMBOL_GPL(meson_clk_mpll_ro_ops);
141 146
142const struct clk_ops meson_clk_mpll_ops = { 147const struct clk_ops meson_clk_mpll_ops = {
143 .recalc_rate = mpll_recalc_rate, 148 .recalc_rate = mpll_recalc_rate,
144 .round_rate = mpll_round_rate, 149 .round_rate = mpll_round_rate,
145 .set_rate = mpll_set_rate, 150 .set_rate = mpll_set_rate,
146}; 151};
152EXPORT_SYMBOL_GPL(meson_clk_mpll_ops);
153
154MODULE_DESCRIPTION("Amlogic MPLL driver");
155MODULE_AUTHOR("Michael Turquette <mturquette@baylibre.com>");
156MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-mpll.h b/drivers/clk/meson/clk-mpll.h
new file mode 100644
index 000000000000..cf79340006dd
--- /dev/null
+++ b/drivers/clk/meson/clk-mpll.h
@@ -0,0 +1,30 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLK_MPLL_H
8#define __MESON_CLK_MPLL_H
9
10#include <linux/clk-provider.h>
11#include <linux/spinlock.h>
12
13#include "parm.h"
14
15struct meson_clk_mpll_data {
16 struct parm sdm;
17 struct parm sdm_en;
18 struct parm n2;
19 struct parm ssen;
20 struct parm misc;
21 spinlock_t *lock;
22 u8 flags;
23};
24
25#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0)
26
27extern const struct clk_ops meson_clk_mpll_ro_ops;
28extern const struct clk_ops meson_clk_mpll_ops;
29
30#endif /* __MESON_CLK_MPLL_H */
diff --git a/drivers/clk/meson/clk-phase.c b/drivers/clk/meson/clk-phase.c
index cba43748ce3d..80c3ada193a4 100644
--- a/drivers/clk/meson/clk-phase.c
+++ b/drivers/clk/meson/clk-phase.c
@@ -5,7 +5,10 @@
5 */ 5 */
6 6
7#include <linux/clk-provider.h> 7#include <linux/clk-provider.h>
8#include "clkc.h" 8#include <linux/module.h>
9
10#include "clk-regmap.h"
11#include "clk-phase.h"
9 12
10#define phase_step(_width) (360 / (1 << (_width))) 13#define phase_step(_width) (360 / (1 << (_width)))
11 14
@@ -15,13 +18,12 @@ meson_clk_phase_data(struct clk_regmap *clk)
15 return (struct meson_clk_phase_data *)clk->data; 18 return (struct meson_clk_phase_data *)clk->data;
16} 19}
17 20
18int meson_clk_degrees_from_val(unsigned int val, unsigned int width) 21static int meson_clk_degrees_from_val(unsigned int val, unsigned int width)
19{ 22{
20 return phase_step(width) * val; 23 return phase_step(width) * val;
21} 24}
22EXPORT_SYMBOL_GPL(meson_clk_degrees_from_val);
23 25
24unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width) 26static unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width)
25{ 27{
26 unsigned int val = DIV_ROUND_CLOSEST(degrees, phase_step(width)); 28 unsigned int val = DIV_ROUND_CLOSEST(degrees, phase_step(width));
27 29
@@ -31,7 +33,6 @@ unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width)
31 */ 33 */
32 return val % (1 << width); 34 return val % (1 << width);
33} 35}
34EXPORT_SYMBOL_GPL(meson_clk_degrees_to_val);
35 36
36static int meson_clk_phase_get_phase(struct clk_hw *hw) 37static int meson_clk_phase_get_phase(struct clk_hw *hw)
37{ 38{
@@ -61,3 +62,67 @@ const struct clk_ops meson_clk_phase_ops = {
61 .set_phase = meson_clk_phase_set_phase, 62 .set_phase = meson_clk_phase_set_phase,
62}; 63};
63EXPORT_SYMBOL_GPL(meson_clk_phase_ops); 64EXPORT_SYMBOL_GPL(meson_clk_phase_ops);
65
66/*
67 * This is a special clock for the audio controller.
68 * The phase of mst_sclk clock output can be controlled independently
69 * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2).
70 * Controlling these 3 phases as just one makes things simpler and
71 * give the same clock view to all the element on the i2s bus.
72 * If necessary, we can still control the phase in the tdm block
73 * which makes these independent control redundant.
74 */
75static inline struct meson_clk_triphase_data *
76meson_clk_triphase_data(struct clk_regmap *clk)
77{
78 return (struct meson_clk_triphase_data *)clk->data;
79}
80
81static void meson_clk_triphase_sync(struct clk_hw *hw)
82{
83 struct clk_regmap *clk = to_clk_regmap(hw);
84 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
85 unsigned int val;
86
87 /* Get phase 0 and sync it to phase 1 and 2 */
88 val = meson_parm_read(clk->map, &tph->ph0);
89 meson_parm_write(clk->map, &tph->ph1, val);
90 meson_parm_write(clk->map, &tph->ph2, val);
91}
92
93static int meson_clk_triphase_get_phase(struct clk_hw *hw)
94{
95 struct clk_regmap *clk = to_clk_regmap(hw);
96 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
97 unsigned int val;
98
99 /* Phase are in sync, reading phase 0 is enough */
100 val = meson_parm_read(clk->map, &tph->ph0);
101
102 return meson_clk_degrees_from_val(val, tph->ph0.width);
103}
104
105static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees)
106{
107 struct clk_regmap *clk = to_clk_regmap(hw);
108 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
109 unsigned int val;
110
111 val = meson_clk_degrees_to_val(degrees, tph->ph0.width);
112 meson_parm_write(clk->map, &tph->ph0, val);
113 meson_parm_write(clk->map, &tph->ph1, val);
114 meson_parm_write(clk->map, &tph->ph2, val);
115
116 return 0;
117}
118
119const struct clk_ops meson_clk_triphase_ops = {
120 .init = meson_clk_triphase_sync,
121 .get_phase = meson_clk_triphase_get_phase,
122 .set_phase = meson_clk_triphase_set_phase,
123};
124EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
125
126MODULE_DESCRIPTION("Amlogic phase driver");
127MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
128MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-phase.h b/drivers/clk/meson/clk-phase.h
new file mode 100644
index 000000000000..5579f9ced142
--- /dev/null
+++ b/drivers/clk/meson/clk-phase.h
@@ -0,0 +1,26 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLK_PHASE_H
8#define __MESON_CLK_PHASE_H
9
10#include <linux/clk-provider.h>
11#include "parm.h"
12
13struct meson_clk_phase_data {
14 struct parm ph;
15};
16
17struct meson_clk_triphase_data {
18 struct parm ph0;
19 struct parm ph1;
20 struct parm ph2;
21};
22
23extern const struct clk_ops meson_clk_phase_ops;
24extern const struct clk_ops meson_clk_triphase_ops;
25
26#endif /* __MESON_CLK_PHASE_H */
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index afffc1547e20..41e16dd7272a 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -32,11 +32,10 @@
32#include <linux/io.h> 32#include <linux/io.h>
33#include <linux/math64.h> 33#include <linux/math64.h>
34#include <linux/module.h> 34#include <linux/module.h>
35#include <linux/of_address.h> 35#include <linux/rational.h>
36#include <linux/slab.h>
37#include <linux/string.h>
38 36
39#include "clkc.h" 37#include "clk-regmap.h"
38#include "clk-pll.h"
40 39
41static inline struct meson_clk_pll_data * 40static inline struct meson_clk_pll_data *
42meson_clk_pll_data(struct clk_regmap *clk) 41meson_clk_pll_data(struct clk_regmap *clk)
@@ -44,12 +43,21 @@ meson_clk_pll_data(struct clk_regmap *clk)
44 return (struct meson_clk_pll_data *)clk->data; 43 return (struct meson_clk_pll_data *)clk->data;
45} 44}
46 45
46static int __pll_round_closest_mult(struct meson_clk_pll_data *pll)
47{
48 if ((pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) &&
49 !MESON_PARM_APPLICABLE(&pll->frac))
50 return 1;
51
52 return 0;
53}
54
47static unsigned long __pll_params_to_rate(unsigned long parent_rate, 55static unsigned long __pll_params_to_rate(unsigned long parent_rate,
48 const struct pll_params_table *pllt, 56 unsigned int m, unsigned int n,
49 u16 frac, 57 unsigned int frac,
50 struct meson_clk_pll_data *pll) 58 struct meson_clk_pll_data *pll)
51{ 59{
52 u64 rate = (u64)parent_rate * pllt->m; 60 u64 rate = (u64)parent_rate * m;
53 61
54 if (frac && MESON_PARM_APPLICABLE(&pll->frac)) { 62 if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
55 u64 frac_rate = (u64)parent_rate * frac; 63 u64 frac_rate = (u64)parent_rate * frac;
@@ -58,7 +66,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
58 (1 << pll->frac.width)); 66 (1 << pll->frac.width));
59 } 67 }
60 68
61 return DIV_ROUND_UP_ULL(rate, pllt->n); 69 return DIV_ROUND_UP_ULL(rate, n);
62} 70}
63 71
64static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw, 72static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -66,35 +74,39 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
66{ 74{
67 struct clk_regmap *clk = to_clk_regmap(hw); 75 struct clk_regmap *clk = to_clk_regmap(hw);
68 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 76 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
69 struct pll_params_table pllt; 77 unsigned int m, n, frac;
70 u16 frac;
71 78
72 pllt.n = meson_parm_read(clk->map, &pll->n); 79 n = meson_parm_read(clk->map, &pll->n);
73 pllt.m = meson_parm_read(clk->map, &pll->m); 80 m = meson_parm_read(clk->map, &pll->m);
74 81
75 frac = MESON_PARM_APPLICABLE(&pll->frac) ? 82 frac = MESON_PARM_APPLICABLE(&pll->frac) ?
76 meson_parm_read(clk->map, &pll->frac) : 83 meson_parm_read(clk->map, &pll->frac) :
77 0; 84 0;
78 85
79 return __pll_params_to_rate(parent_rate, &pllt, frac, pll); 86 return __pll_params_to_rate(parent_rate, m, n, frac, pll);
80} 87}
81 88
82static u16 __pll_params_with_frac(unsigned long rate, 89static unsigned int __pll_params_with_frac(unsigned long rate,
83 unsigned long parent_rate, 90 unsigned long parent_rate,
84 const struct pll_params_table *pllt, 91 unsigned int m,
85 struct meson_clk_pll_data *pll) 92 unsigned int n,
93 struct meson_clk_pll_data *pll)
86{ 94{
87 u16 frac_max = (1 << pll->frac.width); 95 unsigned int frac_max = (1 << pll->frac.width);
88 u64 val = (u64)rate * pllt->n; 96 u64 val = (u64)rate * n;
97
98 /* Bail out if we are already over the requested rate */
99 if (rate < parent_rate * m / n)
100 return 0;
89 101
90 if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) 102 if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
91 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate); 103 val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
92 else 104 else
93 val = div_u64(val * frac_max, parent_rate); 105 val = div_u64(val * frac_max, parent_rate);
94 106
95 val -= pllt->m * frac_max; 107 val -= m * frac_max;
96 108
97 return min((u16)val, (u16)(frac_max - 1)); 109 return min((unsigned int)val, (frac_max - 1));
98} 110}
99 111
100static bool meson_clk_pll_is_better(unsigned long rate, 112static bool meson_clk_pll_is_better(unsigned long rate,
@@ -102,45 +114,123 @@ static bool meson_clk_pll_is_better(unsigned long rate,
102 unsigned long now, 114 unsigned long now,
103 struct meson_clk_pll_data *pll) 115 struct meson_clk_pll_data *pll)
104{ 116{
105 if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) || 117 if (__pll_round_closest_mult(pll)) {
106 MESON_PARM_APPLICABLE(&pll->frac)) {
107 /* Round down */
108 if (now < rate && best < now)
109 return true;
110 } else {
111 /* Round Closest */ 118 /* Round Closest */
112 if (abs(now - rate) < abs(best - rate)) 119 if (abs(now - rate) < abs(best - rate))
113 return true; 120 return true;
121 } else {
122 /* Round down */
123 if (now < rate && best < now)
124 return true;
114 } 125 }
115 126
116 return false; 127 return false;
117} 128}
118 129
119static const struct pll_params_table * 130static int meson_clk_get_pll_table_index(unsigned int index,
120meson_clk_get_pll_settings(unsigned long rate, 131 unsigned int *m,
121 unsigned long parent_rate, 132 unsigned int *n,
122 struct meson_clk_pll_data *pll) 133 struct meson_clk_pll_data *pll)
123{ 134{
124 const struct pll_params_table *table = pll->table; 135 if (!pll->table[index].n)
125 unsigned long best = 0, now = 0; 136 return -EINVAL;
126 unsigned int i, best_i = 0; 137
138 *m = pll->table[index].m;
139 *n = pll->table[index].n;
140
141 return 0;
142}
143
144static unsigned int meson_clk_get_pll_range_m(unsigned long rate,
145 unsigned long parent_rate,
146 unsigned int n,
147 struct meson_clk_pll_data *pll)
148{
149 u64 val = (u64)rate * n;
127 150
128 if (!table) 151 if (__pll_round_closest_mult(pll))
129 return NULL; 152 return DIV_ROUND_CLOSEST_ULL(val, parent_rate);
130 153
131 for (i = 0; table[i].n; i++) { 154 return div_u64(val, parent_rate);
132 now = __pll_params_to_rate(parent_rate, &table[i], 0, pll); 155}
133 156
134 /* If we get an exact match, don't bother any further */ 157static int meson_clk_get_pll_range_index(unsigned long rate,
135 if (now == rate) { 158 unsigned long parent_rate,
136 return &table[i]; 159 unsigned int index,
137 } else if (meson_clk_pll_is_better(rate, best, now, pll)) { 160 unsigned int *m,
161 unsigned int *n,
162 struct meson_clk_pll_data *pll)
163{
164 *n = index + 1;
165
166 /* Check the predivider range */
167 if (*n >= (1 << pll->n.width))
168 return -EINVAL;
169
170 if (*n == 1) {
171 /* Get the boundaries out the way */
172 if (rate <= pll->range->min * parent_rate) {
173 *m = pll->range->min;
174 return -ENODATA;
175 } else if (rate >= pll->range->max * parent_rate) {
176 *m = pll->range->max;
177 return -ENODATA;
178 }
179 }
180
181 *m = meson_clk_get_pll_range_m(rate, parent_rate, *n, pll);
182
183 /* the pre-divider gives a multiplier too big - stop */
184 if (*m >= (1 << pll->m.width))
185 return -EINVAL;
186
187 return 0;
188}
189
190static int meson_clk_get_pll_get_index(unsigned long rate,
191 unsigned long parent_rate,
192 unsigned int index,
193 unsigned int *m,
194 unsigned int *n,
195 struct meson_clk_pll_data *pll)
196{
197 if (pll->range)
198 return meson_clk_get_pll_range_index(rate, parent_rate,
199 index, m, n, pll);
200 else if (pll->table)
201 return meson_clk_get_pll_table_index(index, m, n, pll);
202
203 return -EINVAL;
204}
205
206static int meson_clk_get_pll_settings(unsigned long rate,
207 unsigned long parent_rate,
208 unsigned int *best_m,
209 unsigned int *best_n,
210 struct meson_clk_pll_data *pll)
211{
212 unsigned long best = 0, now = 0;
213 unsigned int i, m, n;
214 int ret;
215
216 for (i = 0, ret = 0; !ret; i++) {
217 ret = meson_clk_get_pll_get_index(rate, parent_rate,
218 i, &m, &n, pll);
219 if (ret == -EINVAL)
220 break;
221
222 now = __pll_params_to_rate(parent_rate, m, n, 0, pll);
223 if (meson_clk_pll_is_better(rate, best, now, pll)) {
138 best = now; 224 best = now;
139 best_i = i; 225 *best_m = m;
226 *best_n = n;
227
228 if (now == rate)
229 break;
140 } 230 }
141 } 231 }
142 232
143 return (struct pll_params_table *)&table[best_i]; 233 return best ? 0 : -EINVAL;
144} 234}
145 235
146static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, 236static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -148,15 +238,15 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
148{ 238{
149 struct clk_regmap *clk = to_clk_regmap(hw); 239 struct clk_regmap *clk = to_clk_regmap(hw);
150 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 240 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
151 const struct pll_params_table *pllt = 241 unsigned int m, n, frac;
152 meson_clk_get_pll_settings(rate, *parent_rate, pll);
153 unsigned long round; 242 unsigned long round;
154 u16 frac; 243 int ret;
155 244
156 if (!pllt) 245 ret = meson_clk_get_pll_settings(rate, *parent_rate, &m, &n, pll);
246 if (ret)
157 return meson_clk_pll_recalc_rate(hw, *parent_rate); 247 return meson_clk_pll_recalc_rate(hw, *parent_rate);
158 248
159 round = __pll_params_to_rate(*parent_rate, pllt, 0, pll); 249 round = __pll_params_to_rate(*parent_rate, m, n, 0, pll);
160 250
161 if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round) 251 if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
162 return round; 252 return round;
@@ -165,9 +255,9 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
165 * The rate provided by the setting is not an exact match, let's 255 * The rate provided by the setting is not an exact match, let's
166 * try to improve the result using the fractional parameter 256 * try to improve the result using the fractional parameter
167 */ 257 */
168 frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll); 258 frac = __pll_params_with_frac(rate, *parent_rate, m, n, pll);
169 259
170 return __pll_params_to_rate(*parent_rate, pllt, frac, pll); 260 return __pll_params_to_rate(*parent_rate, m, n, frac, pll);
171} 261}
172 262
173static int meson_clk_pll_wait_lock(struct clk_hw *hw) 263static int meson_clk_pll_wait_lock(struct clk_hw *hw)
@@ -254,30 +344,27 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
254{ 344{
255 struct clk_regmap *clk = to_clk_regmap(hw); 345 struct clk_regmap *clk = to_clk_regmap(hw);
256 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk); 346 struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
257 const struct pll_params_table *pllt; 347 unsigned int enabled, m, n, frac = 0, ret;
258 unsigned int enabled;
259 unsigned long old_rate; 348 unsigned long old_rate;
260 u16 frac = 0;
261 349
262 if (parent_rate == 0 || rate == 0) 350 if (parent_rate == 0 || rate == 0)
263 return -EINVAL; 351 return -EINVAL;
264 352
265 old_rate = rate; 353 old_rate = rate;
266 354
267 pllt = meson_clk_get_pll_settings(rate, parent_rate, pll); 355 ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll);
268 if (!pllt) 356 if (ret)
269 return -EINVAL; 357 return ret;
270 358
271 enabled = meson_parm_read(clk->map, &pll->en); 359 enabled = meson_parm_read(clk->map, &pll->en);
272 if (enabled) 360 if (enabled)
273 meson_clk_pll_disable(hw); 361 meson_clk_pll_disable(hw);
274 362
275 meson_parm_write(clk->map, &pll->n, pllt->n); 363 meson_parm_write(clk->map, &pll->n, n);
276 meson_parm_write(clk->map, &pll->m, pllt->m); 364 meson_parm_write(clk->map, &pll->m, m);
277
278 365
279 if (MESON_PARM_APPLICABLE(&pll->frac)) { 366 if (MESON_PARM_APPLICABLE(&pll->frac)) {
280 frac = __pll_params_with_frac(rate, parent_rate, pllt, pll); 367 frac = __pll_params_with_frac(rate, parent_rate, m, n, pll);
281 meson_parm_write(clk->map, &pll->frac, frac); 368 meson_parm_write(clk->map, &pll->frac, frac);
282 } 369 }
283 370
@@ -309,8 +396,15 @@ const struct clk_ops meson_clk_pll_ops = {
309 .enable = meson_clk_pll_enable, 396 .enable = meson_clk_pll_enable,
310 .disable = meson_clk_pll_disable 397 .disable = meson_clk_pll_disable
311}; 398};
399EXPORT_SYMBOL_GPL(meson_clk_pll_ops);
312 400
313const struct clk_ops meson_clk_pll_ro_ops = { 401const struct clk_ops meson_clk_pll_ro_ops = {
314 .recalc_rate = meson_clk_pll_recalc_rate, 402 .recalc_rate = meson_clk_pll_recalc_rate,
315 .is_enabled = meson_clk_pll_is_enabled, 403 .is_enabled = meson_clk_pll_is_enabled,
316}; 404};
405EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops);
406
407MODULE_DESCRIPTION("Amlogic PLL driver");
408MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
409MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
410MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
new file mode 100644
index 000000000000..55af2e285b1b
--- /dev/null
+++ b/drivers/clk/meson/clk-pll.h
@@ -0,0 +1,49 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLK_PLL_H
8#define __MESON_CLK_PLL_H
9
10#include <linux/clk-provider.h>
11#include <linux/regmap.h>
12#include "parm.h"
13
14struct pll_params_table {
15 unsigned int m;
16 unsigned int n;
17};
18
19struct pll_mult_range {
20 unsigned int min;
21 unsigned int max;
22};
23
24#define PLL_PARAMS(_m, _n) \
25 { \
26 .m = (_m), \
27 .n = (_n), \
28 }
29
30#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
31
32struct meson_clk_pll_data {
33 struct parm en;
34 struct parm m;
35 struct parm n;
36 struct parm frac;
37 struct parm l;
38 struct parm rst;
39 const struct reg_sequence *init_regs;
40 unsigned int init_count;
41 const struct pll_params_table *table;
42 const struct pll_mult_range *range;
43 u8 flags;
44};
45
46extern const struct clk_ops meson_clk_pll_ro_ops;
47extern const struct clk_ops meson_clk_pll_ops;
48
49#endif /* __MESON_CLK_PLL_H */
diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
index c515f67322a3..dcd1757cc5df 100644
--- a/drivers/clk/meson/clk-regmap.c
+++ b/drivers/clk/meson/clk-regmap.c
@@ -4,6 +4,7 @@
4 * Author: Jerome Brunet <jbrunet@baylibre.com> 4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */ 5 */
6 6
7#include <linux/module.h>
7#include "clk-regmap.h" 8#include "clk-regmap.h"
8 9
9static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable) 10static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
@@ -180,3 +181,7 @@ const struct clk_ops clk_regmap_mux_ro_ops = {
180 .get_parent = clk_regmap_mux_get_parent, 181 .get_parent = clk_regmap_mux_get_parent,
181}; 182};
182EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops); 183EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
184
185MODULE_DESCRIPTION("Amlogic regmap backed clock driver");
186MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
187MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-regmap.h b/drivers/clk/meson/clk-regmap.h
index e9c5728d40eb..1dd0abe3ba91 100644
--- a/drivers/clk/meson/clk-regmap.h
+++ b/drivers/clk/meson/clk-regmap.h
@@ -111,4 +111,24 @@ clk_get_regmap_mux_data(struct clk_regmap *clk)
111extern const struct clk_ops clk_regmap_mux_ops; 111extern const struct clk_ops clk_regmap_mux_ops;
112extern const struct clk_ops clk_regmap_mux_ro_ops; 112extern const struct clk_ops clk_regmap_mux_ro_ops;
113 113
114#define __MESON_GATE(_name, _reg, _bit, _ops) \
115struct clk_regmap _name = { \
116 .data = &(struct clk_regmap_gate_data){ \
117 .offset = (_reg), \
118 .bit_idx = (_bit), \
119 }, \
120 .hw.init = &(struct clk_init_data) { \
121 .name = #_name, \
122 .ops = _ops, \
123 .parent_names = (const char *[]){ "clk81" }, \
124 .num_parents = 1, \
125 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
126 }, \
127}
128
129#define MESON_GATE(_name, _reg, _bit) \
130 __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops)
131
132#define MESON_GATE_RO(_name, _reg, _bit) \
133 __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops)
114#endif /* __CLK_REGMAP_H */ 134#endif /* __CLK_REGMAP_H */
diff --git a/drivers/clk/meson/clk-triphase.c b/drivers/clk/meson/clk-triphase.c
deleted file mode 100644
index 4a59936251e5..000000000000
--- a/drivers/clk/meson/clk-triphase.c
+++ /dev/null
@@ -1,68 +0,0 @@
1// SPDX-License-Identifier: (GPL-2.0 OR MIT)
2/*
3 * Copyright (c) 2018 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#include <linux/clk-provider.h>
8#include "clkc-audio.h"
9
10/*
11 * This is a special clock for the audio controller.
12 * The phase of mst_sclk clock output can be controlled independently
13 * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2).
14 * Controlling these 3 phases as just one makes things simpler and
15 * give the same clock view to all the element on the i2s bus.
16 * If necessary, we can still control the phase in the tdm block
17 * which makes these independent control redundant.
18 */
19static inline struct meson_clk_triphase_data *
20meson_clk_triphase_data(struct clk_regmap *clk)
21{
22 return (struct meson_clk_triphase_data *)clk->data;
23}
24
25static void meson_clk_triphase_sync(struct clk_hw *hw)
26{
27 struct clk_regmap *clk = to_clk_regmap(hw);
28 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
29 unsigned int val;
30
31 /* Get phase 0 and sync it to phase 1 and 2 */
32 val = meson_parm_read(clk->map, &tph->ph0);
33 meson_parm_write(clk->map, &tph->ph1, val);
34 meson_parm_write(clk->map, &tph->ph2, val);
35}
36
37static int meson_clk_triphase_get_phase(struct clk_hw *hw)
38{
39 struct clk_regmap *clk = to_clk_regmap(hw);
40 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
41 unsigned int val;
42
43 /* Phase are in sync, reading phase 0 is enough */
44 val = meson_parm_read(clk->map, &tph->ph0);
45
46 return meson_clk_degrees_from_val(val, tph->ph0.width);
47}
48
49static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees)
50{
51 struct clk_regmap *clk = to_clk_regmap(hw);
52 struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
53 unsigned int val;
54
55 val = meson_clk_degrees_to_val(degrees, tph->ph0.width);
56 meson_parm_write(clk->map, &tph->ph0, val);
57 meson_parm_write(clk->map, &tph->ph1, val);
58 meson_parm_write(clk->map, &tph->ph2, val);
59
60 return 0;
61}
62
63const struct clk_ops meson_clk_triphase_ops = {
64 .init = meson_clk_triphase_sync,
65 .get_phase = meson_clk_triphase_get_phase,
66 .set_phase = meson_clk_triphase_set_phase,
67};
68EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
deleted file mode 100644
index 6183b22c4bf2..000000000000
--- a/drivers/clk/meson/clkc.h
+++ /dev/null
@@ -1,127 +0,0 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2015 Endless Mobile, Inc.
4 * Author: Carlo Caione <carlo@endlessm.com>
5 */
6
7#ifndef __CLKC_H
8#define __CLKC_H
9
10#include <linux/clk-provider.h>
11#include "clk-regmap.h"
12
13#define PMASK(width) GENMASK(width - 1, 0)
14#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
15#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
16
17#define PARM_GET(width, shift, reg) \
18 (((reg) & SETPMASK(width, shift)) >> (shift))
19#define PARM_SET(width, shift, reg, val) \
20 (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
21
22#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
23
24struct parm {
25 u16 reg_off;
26 u8 shift;
27 u8 width;
28};
29
30static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
31{
32 unsigned int val;
33
34 regmap_read(map, p->reg_off, &val);
35 return PARM_GET(p->width, p->shift, val);
36}
37
38static inline void meson_parm_write(struct regmap *map, struct parm *p,
39 unsigned int val)
40{
41 regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
42 val << p->shift);
43}
44
45
46struct pll_params_table {
47 u16 m;
48 u16 n;
49};
50
51#define PLL_PARAMS(_m, _n) \
52 { \
53 .m = (_m), \
54 .n = (_n), \
55 }
56
57#define CLK_MESON_PLL_ROUND_CLOSEST BIT(0)
58
59struct meson_clk_pll_data {
60 struct parm en;
61 struct parm m;
62 struct parm n;
63 struct parm frac;
64 struct parm l;
65 struct parm rst;
66 const struct reg_sequence *init_regs;
67 unsigned int init_count;
68 const struct pll_params_table *table;
69 u8 flags;
70};
71
72#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
73
74struct meson_clk_mpll_data {
75 struct parm sdm;
76 struct parm sdm_en;
77 struct parm n2;
78 struct parm ssen;
79 struct parm misc;
80 spinlock_t *lock;
81 u8 flags;
82};
83
84#define CLK_MESON_MPLL_ROUND_CLOSEST BIT(0)
85
86struct meson_clk_phase_data {
87 struct parm ph;
88};
89
90int meson_clk_degrees_from_val(unsigned int val, unsigned int width);
91unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width);
92
93struct meson_vid_pll_div_data {
94 struct parm val;
95 struct parm sel;
96};
97
98#define MESON_GATE(_name, _reg, _bit) \
99struct clk_regmap _name = { \
100 .data = &(struct clk_regmap_gate_data){ \
101 .offset = (_reg), \
102 .bit_idx = (_bit), \
103 }, \
104 .hw.init = &(struct clk_init_data) { \
105 .name = #_name, \
106 .ops = &clk_regmap_gate_ops, \
107 .parent_names = (const char *[]){ "clk81" }, \
108 .num_parents = 1, \
109 .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED), \
110 }, \
111};
112
113/* clk_ops */
114extern const struct clk_ops meson_clk_pll_ro_ops;
115extern const struct clk_ops meson_clk_pll_ops;
116extern const struct clk_ops meson_clk_cpu_ops;
117extern const struct clk_ops meson_clk_mpll_ro_ops;
118extern const struct clk_ops meson_clk_mpll_ops;
119extern const struct clk_ops meson_clk_phase_ops;
120extern const struct clk_ops meson_vid_pll_div_ro_ops;
121
122struct clk_hw *meson_clk_hw_register_input(struct device *dev,
123 const char *of_name,
124 const char *clk_name,
125 unsigned long flags);
126
127#endif /* __CLKC_H */
diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c
new file mode 100644
index 000000000000..1994e735396b
--- /dev/null
+++ b/drivers/clk/meson/g12a-aoclk.c
@@ -0,0 +1,454 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Amlogic Meson-AXG Clock Controller Driver
4 *
5 * Copyright (c) 2016 Baylibre SAS.
6 * Author: Michael Turquette <mturquette@baylibre.com>
7 *
8 * Copyright (c) 2019 Baylibre SAS.
9 * Author: Neil Armstrong <narmstrong@baylibre.com>
10 */
11#include <linux/clk-provider.h>
12#include <linux/platform_device.h>
13#include <linux/reset-controller.h>
14#include <linux/mfd/syscon.h>
15#include "meson-aoclk.h"
16#include "g12a-aoclk.h"
17
18#include "clk-regmap.h"
19#include "clk-dualdiv.h"
20
21#define IN_PREFIX "ao-in-"
22
23/*
24 * AO Configuration Clock registers offsets
25 * Register offsets from the data sheet must be multiplied by 4.
26 */
27#define AO_RTI_STATUS_REG3 0x0C
28#define AO_RTI_PWR_CNTL_REG0 0x10
29#define AO_RTI_GEN_CNTL_REG0 0x40
30#define AO_CLK_GATE0 0x4c
31#define AO_CLK_GATE0_SP 0x50
32#define AO_OSCIN_CNTL 0x58
33#define AO_CEC_CLK_CNTL_REG0 0x74
34#define AO_CEC_CLK_CNTL_REG1 0x78
35#define AO_SAR_CLK 0x90
36#define AO_RTC_ALT_CLK_CNTL0 0x94
37#define AO_RTC_ALT_CLK_CNTL1 0x98
38
39/*
40 * Like every other peripheral clock gate in Amlogic Clock drivers,
41 * we are using CLK_IGNORE_UNUSED here, so we keep the state of the
42 * bootloader. The goal is to remove this flag at some point.
43 * Actually removing it will require some extensive test to be done safely.
44 */
45#define AXG_AO_GATE(_name, _reg, _bit) \
46static struct clk_regmap g12a_aoclk_##_name = { \
47 .data = &(struct clk_regmap_gate_data) { \
48 .offset = (_reg), \
49 .bit_idx = (_bit), \
50 }, \
51 .hw.init = &(struct clk_init_data) { \
52 .name = "g12a_ao_" #_name, \
53 .ops = &clk_regmap_gate_ops, \
54 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
55 .num_parents = 1, \
56 .flags = CLK_IGNORE_UNUSED, \
57 }, \
58}
59
60AXG_AO_GATE(ahb, AO_CLK_GATE0, 0);
61AXG_AO_GATE(ir_in, AO_CLK_GATE0, 1);
62AXG_AO_GATE(i2c_m0, AO_CLK_GATE0, 2);
63AXG_AO_GATE(i2c_s0, AO_CLK_GATE0, 3);
64AXG_AO_GATE(uart, AO_CLK_GATE0, 4);
65AXG_AO_GATE(prod_i2c, AO_CLK_GATE0, 5);
66AXG_AO_GATE(uart2, AO_CLK_GATE0, 6);
67AXG_AO_GATE(ir_out, AO_CLK_GATE0, 7);
68AXG_AO_GATE(saradc, AO_CLK_GATE0, 8);
69AXG_AO_GATE(mailbox, AO_CLK_GATE0_SP, 0);
70AXG_AO_GATE(m3, AO_CLK_GATE0_SP, 1);
71AXG_AO_GATE(ahb_sram, AO_CLK_GATE0_SP, 2);
72AXG_AO_GATE(rti, AO_CLK_GATE0_SP, 3);
73AXG_AO_GATE(m4_fclk, AO_CLK_GATE0_SP, 4);
74AXG_AO_GATE(m4_hclk, AO_CLK_GATE0_SP, 5);
75
76static struct clk_regmap g12a_aoclk_cts_oscin = {
77 .data = &(struct clk_regmap_gate_data){
78 .offset = AO_RTI_PWR_CNTL_REG0,
79 .bit_idx = 14,
80 },
81 .hw.init = &(struct clk_init_data){
82 .name = "cts_oscin",
83 .ops = &clk_regmap_gate_ro_ops,
84 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
85 .num_parents = 1,
86 },
87};
88
89static const struct meson_clk_dualdiv_param g12a_32k_div_table[] = {
90 {
91 .dual = 1,
92 .n1 = 733,
93 .m1 = 8,
94 .n2 = 732,
95 .m2 = 11,
96 }, {}
97};
98
99/* 32k_by_oscin clock */
100
101static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = {
102 .data = &(struct clk_regmap_gate_data){
103 .offset = AO_RTC_ALT_CLK_CNTL0,
104 .bit_idx = 31,
105 },
106 .hw.init = &(struct clk_init_data){
107 .name = "g12a_ao_32k_by_oscin_pre",
108 .ops = &clk_regmap_gate_ops,
109 .parent_names = (const char *[]){ "cts_oscin" },
110 .num_parents = 1,
111 },
112};
113
114static struct clk_regmap g12a_aoclk_32k_by_oscin_div = {
115 .data = &(struct meson_clk_dualdiv_data){
116 .n1 = {
117 .reg_off = AO_RTC_ALT_CLK_CNTL0,
118 .shift = 0,
119 .width = 12,
120 },
121 .n2 = {
122 .reg_off = AO_RTC_ALT_CLK_CNTL0,
123 .shift = 12,
124 .width = 12,
125 },
126 .m1 = {
127 .reg_off = AO_RTC_ALT_CLK_CNTL1,
128 .shift = 0,
129 .width = 12,
130 },
131 .m2 = {
132 .reg_off = AO_RTC_ALT_CLK_CNTL1,
133 .shift = 12,
134 .width = 12,
135 },
136 .dual = {
137 .reg_off = AO_RTC_ALT_CLK_CNTL0,
138 .shift = 28,
139 .width = 1,
140 },
141 .table = g12a_32k_div_table,
142 },
143 .hw.init = &(struct clk_init_data){
144 .name = "g12a_ao_32k_by_oscin_div",
145 .ops = &meson_clk_dualdiv_ops,
146 .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" },
147 .num_parents = 1,
148 },
149};
150
151static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = {
152 .data = &(struct clk_regmap_mux_data) {
153 .offset = AO_RTC_ALT_CLK_CNTL1,
154 .mask = 0x1,
155 .shift = 24,
156 .flags = CLK_MUX_ROUND_CLOSEST,
157 },
158 .hw.init = &(struct clk_init_data){
159 .name = "g12a_ao_32k_by_oscin_sel",
160 .ops = &clk_regmap_mux_ops,
161 .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div",
162 "g12a_ao_32k_by_oscin_pre" },
163 .num_parents = 2,
164 .flags = CLK_SET_RATE_PARENT,
165 },
166};
167
168static struct clk_regmap g12a_aoclk_32k_by_oscin = {
169 .data = &(struct clk_regmap_gate_data){
170 .offset = AO_RTC_ALT_CLK_CNTL0,
171 .bit_idx = 30,
172 },
173 .hw.init = &(struct clk_init_data){
174 .name = "g12a_ao_32k_by_oscin",
175 .ops = &clk_regmap_gate_ops,
176 .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" },
177 .num_parents = 1,
178 .flags = CLK_SET_RATE_PARENT,
179 },
180};
181
182/* cec clock */
183
184static struct clk_regmap g12a_aoclk_cec_pre = {
185 .data = &(struct clk_regmap_gate_data){
186 .offset = AO_CEC_CLK_CNTL_REG0,
187 .bit_idx = 31,
188 },
189 .hw.init = &(struct clk_init_data){
190 .name = "g12a_ao_cec_pre",
191 .ops = &clk_regmap_gate_ops,
192 .parent_names = (const char *[]){ "cts_oscin" },
193 .num_parents = 1,
194 },
195};
196
197static struct clk_regmap g12a_aoclk_cec_div = {
198 .data = &(struct meson_clk_dualdiv_data){
199 .n1 = {
200 .reg_off = AO_CEC_CLK_CNTL_REG0,
201 .shift = 0,
202 .width = 12,
203 },
204 .n2 = {
205 .reg_off = AO_CEC_CLK_CNTL_REG0,
206 .shift = 12,
207 .width = 12,
208 },
209 .m1 = {
210 .reg_off = AO_CEC_CLK_CNTL_REG1,
211 .shift = 0,
212 .width = 12,
213 },
214 .m2 = {
215 .reg_off = AO_CEC_CLK_CNTL_REG1,
216 .shift = 12,
217 .width = 12,
218 },
219 .dual = {
220 .reg_off = AO_CEC_CLK_CNTL_REG0,
221 .shift = 28,
222 .width = 1,
223 },
224 .table = g12a_32k_div_table,
225 },
226 .hw.init = &(struct clk_init_data){
227 .name = "g12a_ao_cec_div",
228 .ops = &meson_clk_dualdiv_ops,
229 .parent_names = (const char *[]){ "g12a_ao_cec_pre" },
230 .num_parents = 1,
231 },
232};
233
234static struct clk_regmap g12a_aoclk_cec_sel = {
235 .data = &(struct clk_regmap_mux_data) {
236 .offset = AO_CEC_CLK_CNTL_REG1,
237 .mask = 0x1,
238 .shift = 24,
239 .flags = CLK_MUX_ROUND_CLOSEST,
240 },
241 .hw.init = &(struct clk_init_data){
242 .name = "g12a_ao_cec_sel",
243 .ops = &clk_regmap_mux_ops,
244 .parent_names = (const char *[]){ "g12a_ao_cec_div",
245 "g12a_ao_cec_pre" },
246 .num_parents = 2,
247 .flags = CLK_SET_RATE_PARENT,
248 },
249};
250
251static struct clk_regmap g12a_aoclk_cec = {
252 .data = &(struct clk_regmap_gate_data){
253 .offset = AO_CEC_CLK_CNTL_REG0,
254 .bit_idx = 30,
255 },
256 .hw.init = &(struct clk_init_data){
257 .name = "g12a_ao_cec",
258 .ops = &clk_regmap_gate_ops,
259 .parent_names = (const char *[]){ "g12a_ao_cec_sel" },
260 .num_parents = 1,
261 .flags = CLK_SET_RATE_PARENT,
262 },
263};
264
265static struct clk_regmap g12a_aoclk_cts_rtc_oscin = {
266 .data = &(struct clk_regmap_mux_data) {
267 .offset = AO_RTI_PWR_CNTL_REG0,
268 .mask = 0x1,
269 .shift = 10,
270 .flags = CLK_MUX_ROUND_CLOSEST,
271 },
272 .hw.init = &(struct clk_init_data){
273 .name = "g12a_ao_cts_rtc_oscin",
274 .ops = &clk_regmap_mux_ops,
275 .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin",
276 IN_PREFIX "ext_32k-0" },
277 .num_parents = 2,
278 .flags = CLK_SET_RATE_PARENT,
279 },
280};
281
282static struct clk_regmap g12a_aoclk_clk81 = {
283 .data = &(struct clk_regmap_mux_data) {
284 .offset = AO_RTI_PWR_CNTL_REG0,
285 .mask = 0x1,
286 .shift = 8,
287 .flags = CLK_MUX_ROUND_CLOSEST,
288 },
289 .hw.init = &(struct clk_init_data){
290 .name = "g12a_ao_clk81",
291 .ops = &clk_regmap_mux_ro_ops,
292 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
293 "g12a_ao_cts_rtc_oscin"},
294 .num_parents = 2,
295 .flags = CLK_SET_RATE_PARENT,
296 },
297};
298
299static struct clk_regmap g12a_aoclk_saradc_mux = {
300 .data = &(struct clk_regmap_mux_data) {
301 .offset = AO_SAR_CLK,
302 .mask = 0x3,
303 .shift = 9,
304 },
305 .hw.init = &(struct clk_init_data){
306 .name = "g12a_ao_saradc_mux",
307 .ops = &clk_regmap_mux_ops,
308 .parent_names = (const char *[]){ IN_PREFIX "xtal",
309 "g12a_ao_clk81" },
310 .num_parents = 2,
311 },
312};
313
314static struct clk_regmap g12a_aoclk_saradc_div = {
315 .data = &(struct clk_regmap_div_data) {
316 .offset = AO_SAR_CLK,
317 .shift = 0,
318 .width = 8,
319 },
320 .hw.init = &(struct clk_init_data){
321 .name = "g12a_ao_saradc_div",
322 .ops = &clk_regmap_divider_ops,
323 .parent_names = (const char *[]){ "g12a_ao_saradc_mux" },
324 .num_parents = 1,
325 .flags = CLK_SET_RATE_PARENT,
326 },
327};
328
329static struct clk_regmap g12a_aoclk_saradc_gate = {
330 .data = &(struct clk_regmap_gate_data) {
331 .offset = AO_SAR_CLK,
332 .bit_idx = 8,
333 },
334 .hw.init = &(struct clk_init_data){
335 .name = "g12a_ao_saradc_gate",
336 .ops = &clk_regmap_gate_ops,
337 .parent_names = (const char *[]){ "g12a_ao_saradc_div" },
338 .num_parents = 1,
339 .flags = CLK_SET_RATE_PARENT,
340 },
341};
342
343static const unsigned int g12a_aoclk_reset[] = {
344 [RESET_AO_IR_IN] = 16,
345 [RESET_AO_UART] = 17,
346 [RESET_AO_I2C_M] = 18,
347 [RESET_AO_I2C_S] = 19,
348 [RESET_AO_SAR_ADC] = 20,
349 [RESET_AO_UART2] = 22,
350 [RESET_AO_IR_OUT] = 23,
351};
352
353static struct clk_regmap *g12a_aoclk_regmap[] = {
354 &g12a_aoclk_ahb,
355 &g12a_aoclk_ir_in,
356 &g12a_aoclk_i2c_m0,
357 &g12a_aoclk_i2c_s0,
358 &g12a_aoclk_uart,
359 &g12a_aoclk_prod_i2c,
360 &g12a_aoclk_uart2,
361 &g12a_aoclk_ir_out,
362 &g12a_aoclk_saradc,
363 &g12a_aoclk_mailbox,
364 &g12a_aoclk_m3,
365 &g12a_aoclk_ahb_sram,
366 &g12a_aoclk_rti,
367 &g12a_aoclk_m4_fclk,
368 &g12a_aoclk_m4_hclk,
369 &g12a_aoclk_cts_oscin,
370 &g12a_aoclk_32k_by_oscin_pre,
371 &g12a_aoclk_32k_by_oscin_div,
372 &g12a_aoclk_32k_by_oscin_sel,
373 &g12a_aoclk_32k_by_oscin,
374 &g12a_aoclk_cec_pre,
375 &g12a_aoclk_cec_div,
376 &g12a_aoclk_cec_sel,
377 &g12a_aoclk_cec,
378 &g12a_aoclk_cts_rtc_oscin,
379 &g12a_aoclk_clk81,
380 &g12a_aoclk_saradc_mux,
381 &g12a_aoclk_saradc_div,
382 &g12a_aoclk_saradc_gate,
383};
384
385static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = {
386 .hws = {
387 [CLKID_AO_AHB] = &g12a_aoclk_ahb.hw,
388 [CLKID_AO_IR_IN] = &g12a_aoclk_ir_in.hw,
389 [CLKID_AO_I2C_M0] = &g12a_aoclk_i2c_m0.hw,
390 [CLKID_AO_I2C_S0] = &g12a_aoclk_i2c_s0.hw,
391 [CLKID_AO_UART] = &g12a_aoclk_uart.hw,
392 [CLKID_AO_PROD_I2C] = &g12a_aoclk_prod_i2c.hw,
393 [CLKID_AO_UART2] = &g12a_aoclk_uart2.hw,
394 [CLKID_AO_IR_OUT] = &g12a_aoclk_ir_out.hw,
395 [CLKID_AO_SAR_ADC] = &g12a_aoclk_saradc.hw,
396 [CLKID_AO_MAILBOX] = &g12a_aoclk_mailbox.hw,
397 [CLKID_AO_M3] = &g12a_aoclk_m3.hw,
398 [CLKID_AO_AHB_SRAM] = &g12a_aoclk_ahb_sram.hw,
399 [CLKID_AO_RTI] = &g12a_aoclk_rti.hw,
400 [CLKID_AO_M4_FCLK] = &g12a_aoclk_m4_fclk.hw,
401 [CLKID_AO_M4_HCLK] = &g12a_aoclk_m4_hclk.hw,
402 [CLKID_AO_CLK81] = &g12a_aoclk_clk81.hw,
403 [CLKID_AO_SAR_ADC_SEL] = &g12a_aoclk_saradc_mux.hw,
404 [CLKID_AO_SAR_ADC_DIV] = &g12a_aoclk_saradc_div.hw,
405 [CLKID_AO_SAR_ADC_CLK] = &g12a_aoclk_saradc_gate.hw,
406 [CLKID_AO_CTS_OSCIN] = &g12a_aoclk_cts_oscin.hw,
407 [CLKID_AO_32K_PRE] = &g12a_aoclk_32k_by_oscin_pre.hw,
408 [CLKID_AO_32K_DIV] = &g12a_aoclk_32k_by_oscin_div.hw,
409 [CLKID_AO_32K_SEL] = &g12a_aoclk_32k_by_oscin_sel.hw,
410 [CLKID_AO_32K] = &g12a_aoclk_32k_by_oscin.hw,
411 [CLKID_AO_CEC_PRE] = &g12a_aoclk_cec_pre.hw,
412 [CLKID_AO_CEC_DIV] = &g12a_aoclk_cec_div.hw,
413 [CLKID_AO_CEC_SEL] = &g12a_aoclk_cec_sel.hw,
414 [CLKID_AO_CEC] = &g12a_aoclk_cec.hw,
415 [CLKID_AO_CTS_RTC_OSCIN] = &g12a_aoclk_cts_rtc_oscin.hw,
416 },
417 .num = NR_CLKS,
418};
419
420static const struct meson_aoclk_input g12a_aoclk_inputs[] = {
421 { .name = "xtal", .required = true },
422 { .name = "mpeg-clk", .required = true },
423 { .name = "ext-32k-0", .required = false },
424};
425
426static const struct meson_aoclk_data g12a_aoclkc_data = {
427 .reset_reg = AO_RTI_GEN_CNTL_REG0,
428 .num_reset = ARRAY_SIZE(g12a_aoclk_reset),
429 .reset = g12a_aoclk_reset,
430 .num_clks = ARRAY_SIZE(g12a_aoclk_regmap),
431 .clks = g12a_aoclk_regmap,
432 .hw_data = &g12a_aoclk_onecell_data,
433 .inputs = g12a_aoclk_inputs,
434 .num_inputs = ARRAY_SIZE(g12a_aoclk_inputs),
435 .input_prefix = IN_PREFIX,
436};
437
438static const struct of_device_id g12a_aoclkc_match_table[] = {
439 {
440 .compatible = "amlogic,meson-g12a-aoclkc",
441 .data = &g12a_aoclkc_data,
442 },
443 { }
444};
445
446static struct platform_driver g12a_aoclkc_driver = {
447 .probe = meson_aoclkc_probe,
448 .driver = {
449 .name = "g12a-aoclkc",
450 .of_match_table = g12a_aoclkc_match_table,
451 },
452};
453
454builtin_platform_driver(g12a_aoclkc_driver);
diff --git a/drivers/clk/meson/g12a-aoclk.h b/drivers/clk/meson/g12a-aoclk.h
new file mode 100644
index 000000000000..04b0d5506641
--- /dev/null
+++ b/drivers/clk/meson/g12a-aoclk.h
@@ -0,0 +1,34 @@
1/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2/*
3 * Copyright (c) 2019 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6
7#ifndef __G12A_AOCLKC_H
8#define __G12A_AOCLKC_H
9
10/*
11 * CLKID index values
12 *
13 * These indices are entirely contrived and do not map onto the hardware.
14 * It has now been decided to expose everything by default in the DT header:
15 * include/dt-bindings/clock/g12a-aoclkc.h. Only the clocks ids we don't want
16 * to expose, such as the internal muxes and dividers of composite clocks,
17 * will remain defined here.
18 */
19#define CLKID_AO_SAR_ADC_SEL 16
20#define CLKID_AO_SAR_ADC_DIV 17
21#define CLKID_AO_CTS_OSCIN 19
22#define CLKID_AO_32K_PRE 20
23#define CLKID_AO_32K_DIV 21
24#define CLKID_AO_32K_SEL 22
25#define CLKID_AO_CEC_PRE 24
26#define CLKID_AO_CEC_DIV 25
27#define CLKID_AO_CEC_SEL 26
28
29#define NR_CLKS 29
30
31#include <dt-bindings/clock/g12a-aoclkc.h>
32#include <dt-bindings/reset/g12a-aoclkc.h>
33
34#endif /* __G12A_AOCLKC_H */
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
new file mode 100644
index 000000000000..0e1ce8c03259
--- /dev/null
+++ b/drivers/clk/meson/g12a.c
@@ -0,0 +1,2359 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Amlogic Meson-G12A Clock Controller Driver
4 *
5 * Copyright (c) 2016 Baylibre SAS.
6 * Author: Michael Turquette <mturquette@baylibre.com>
7 *
8 * Copyright (c) 2018 Amlogic, inc.
9 * Author: Qiufang Dai <qiufang.dai@amlogic.com>
10 * Author: Jian Hu <jian.hu@amlogic.com>
11 */
12
13#include <linux/clk-provider.h>
14#include <linux/init.h>
15#include <linux/of_device.h>
16#include <linux/platform_device.h>
17
18#include "clk-input.h"
19#include "clk-mpll.h"
20#include "clk-pll.h"
21#include "clk-regmap.h"
22#include "vid-pll-div.h"
23#include "meson-eeclk.h"
24#include "g12a.h"
25
26static DEFINE_SPINLOCK(meson_clk_lock);
27
28static struct clk_regmap g12a_fixed_pll_dco = {
29 .data = &(struct meson_clk_pll_data){
30 .en = {
31 .reg_off = HHI_FIX_PLL_CNTL0,
32 .shift = 28,
33 .width = 1,
34 },
35 .m = {
36 .reg_off = HHI_FIX_PLL_CNTL0,
37 .shift = 0,
38 .width = 8,
39 },
40 .n = {
41 .reg_off = HHI_FIX_PLL_CNTL0,
42 .shift = 10,
43 .width = 5,
44 },
45 .frac = {
46 .reg_off = HHI_FIX_PLL_CNTL1,
47 .shift = 0,
48 .width = 17,
49 },
50 .l = {
51 .reg_off = HHI_FIX_PLL_CNTL0,
52 .shift = 31,
53 .width = 1,
54 },
55 .rst = {
56 .reg_off = HHI_FIX_PLL_CNTL0,
57 .shift = 29,
58 .width = 1,
59 },
60 },
61 .hw.init = &(struct clk_init_data){
62 .name = "fixed_pll_dco",
63 .ops = &meson_clk_pll_ro_ops,
64 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
65 .num_parents = 1,
66 },
67};
68
69static struct clk_regmap g12a_fixed_pll = {
70 .data = &(struct clk_regmap_div_data){
71 .offset = HHI_FIX_PLL_CNTL0,
72 .shift = 16,
73 .width = 2,
74 .flags = CLK_DIVIDER_POWER_OF_TWO,
75 },
76 .hw.init = &(struct clk_init_data){
77 .name = "fixed_pll",
78 .ops = &clk_regmap_divider_ro_ops,
79 .parent_names = (const char *[]){ "fixed_pll_dco" },
80 .num_parents = 1,
81 /*
82 * This clock won't ever change at runtime so
83 * CLK_SET_RATE_PARENT is not required
84 */
85 },
86};
87
88/*
89 * Internal sys pll emulation configuration parameters
90 */
91static const struct reg_sequence g12a_sys_init_regs[] = {
92 { .reg = HHI_SYS_PLL_CNTL1, .def = 0x00000000 },
93 { .reg = HHI_SYS_PLL_CNTL2, .def = 0x00000000 },
94 { .reg = HHI_SYS_PLL_CNTL3, .def = 0x48681c00 },
95 { .reg = HHI_SYS_PLL_CNTL4, .def = 0x88770290 },
96 { .reg = HHI_SYS_PLL_CNTL5, .def = 0x39272000 },
97 { .reg = HHI_SYS_PLL_CNTL6, .def = 0x56540000 },
98};
99
100static struct clk_regmap g12a_sys_pll_dco = {
101 .data = &(struct meson_clk_pll_data){
102 .en = {
103 .reg_off = HHI_SYS_PLL_CNTL0,
104 .shift = 28,
105 .width = 1,
106 },
107 .m = {
108 .reg_off = HHI_SYS_PLL_CNTL0,
109 .shift = 0,
110 .width = 8,
111 },
112 .n = {
113 .reg_off = HHI_SYS_PLL_CNTL0,
114 .shift = 10,
115 .width = 5,
116 },
117 .l = {
118 .reg_off = HHI_SYS_PLL_CNTL0,
119 .shift = 31,
120 .width = 1,
121 },
122 .rst = {
123 .reg_off = HHI_SYS_PLL_CNTL0,
124 .shift = 29,
125 .width = 1,
126 },
127 .init_regs = g12a_sys_init_regs,
128 .init_count = ARRAY_SIZE(g12a_sys_init_regs),
129 },
130 .hw.init = &(struct clk_init_data){
131 .name = "sys_pll_dco",
132 .ops = &meson_clk_pll_ro_ops,
133 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
134 .num_parents = 1,
135 },
136};
137
138static struct clk_regmap g12a_sys_pll = {
139 .data = &(struct clk_regmap_div_data){
140 .offset = HHI_SYS_PLL_CNTL0,
141 .shift = 16,
142 .width = 3,
143 .flags = CLK_DIVIDER_POWER_OF_TWO,
144 },
145 .hw.init = &(struct clk_init_data){
146 .name = "sys_pll",
147 .ops = &clk_regmap_divider_ro_ops,
148 .parent_names = (const char *[]){ "sys_pll_dco" },
149 .num_parents = 1,
150 },
151};
152
153static const struct pll_mult_range g12a_gp0_pll_mult_range = {
154 .min = 55,
155 .max = 255,
156};
157
158/*
159 * Internal gp0 pll emulation configuration parameters
160 */
161static const struct reg_sequence g12a_gp0_init_regs[] = {
162 { .reg = HHI_GP0_PLL_CNTL1, .def = 0x00000000 },
163 { .reg = HHI_GP0_PLL_CNTL2, .def = 0x00000000 },
164 { .reg = HHI_GP0_PLL_CNTL3, .def = 0x48681c00 },
165 { .reg = HHI_GP0_PLL_CNTL4, .def = 0x33771290 },
166 { .reg = HHI_GP0_PLL_CNTL5, .def = 0x39272000 },
167 { .reg = HHI_GP0_PLL_CNTL6, .def = 0x56540000 },
168};
169
170static struct clk_regmap g12a_gp0_pll_dco = {
171 .data = &(struct meson_clk_pll_data){
172 .en = {
173 .reg_off = HHI_GP0_PLL_CNTL0,
174 .shift = 28,
175 .width = 1,
176 },
177 .m = {
178 .reg_off = HHI_GP0_PLL_CNTL0,
179 .shift = 0,
180 .width = 8,
181 },
182 .n = {
183 .reg_off = HHI_GP0_PLL_CNTL0,
184 .shift = 10,
185 .width = 5,
186 },
187 .frac = {
188 .reg_off = HHI_GP0_PLL_CNTL1,
189 .shift = 0,
190 .width = 17,
191 },
192 .l = {
193 .reg_off = HHI_GP0_PLL_CNTL0,
194 .shift = 31,
195 .width = 1,
196 },
197 .rst = {
198 .reg_off = HHI_GP0_PLL_CNTL0,
199 .shift = 29,
200 .width = 1,
201 },
202 .range = &g12a_gp0_pll_mult_range,
203 .init_regs = g12a_gp0_init_regs,
204 .init_count = ARRAY_SIZE(g12a_gp0_init_regs),
205 },
206 .hw.init = &(struct clk_init_data){
207 .name = "gp0_pll_dco",
208 .ops = &meson_clk_pll_ops,
209 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
210 .num_parents = 1,
211 },
212};
213
214static struct clk_regmap g12a_gp0_pll = {
215 .data = &(struct clk_regmap_div_data){
216 .offset = HHI_GP0_PLL_CNTL0,
217 .shift = 16,
218 .width = 3,
219 .flags = (CLK_DIVIDER_POWER_OF_TWO |
220 CLK_DIVIDER_ROUND_CLOSEST),
221 },
222 .hw.init = &(struct clk_init_data){
223 .name = "gp0_pll",
224 .ops = &clk_regmap_divider_ops,
225 .parent_names = (const char *[]){ "gp0_pll_dco" },
226 .num_parents = 1,
227 .flags = CLK_SET_RATE_PARENT,
228 },
229};
230
231/*
232 * Internal hifi pll emulation configuration parameters
233 */
234static const struct reg_sequence g12a_hifi_init_regs[] = {
235 { .reg = HHI_HIFI_PLL_CNTL1, .def = 0x00000000 },
236 { .reg = HHI_HIFI_PLL_CNTL2, .def = 0x00000000 },
237 { .reg = HHI_HIFI_PLL_CNTL3, .def = 0x6a285c00 },
238 { .reg = HHI_HIFI_PLL_CNTL4, .def = 0x65771290 },
239 { .reg = HHI_HIFI_PLL_CNTL5, .def = 0x39272000 },
240 { .reg = HHI_HIFI_PLL_CNTL6, .def = 0x56540000 },
241};
242
243static struct clk_regmap g12a_hifi_pll_dco = {
244 .data = &(struct meson_clk_pll_data){
245 .en = {
246 .reg_off = HHI_HIFI_PLL_CNTL0,
247 .shift = 28,
248 .width = 1,
249 },
250 .m = {
251 .reg_off = HHI_HIFI_PLL_CNTL0,
252 .shift = 0,
253 .width = 8,
254 },
255 .n = {
256 .reg_off = HHI_HIFI_PLL_CNTL0,
257 .shift = 10,
258 .width = 5,
259 },
260 .frac = {
261 .reg_off = HHI_HIFI_PLL_CNTL1,
262 .shift = 0,
263 .width = 17,
264 },
265 .l = {
266 .reg_off = HHI_HIFI_PLL_CNTL0,
267 .shift = 31,
268 .width = 1,
269 },
270 .rst = {
271 .reg_off = HHI_HIFI_PLL_CNTL0,
272 .shift = 29,
273 .width = 1,
274 },
275 .range = &g12a_gp0_pll_mult_range,
276 .init_regs = g12a_hifi_init_regs,
277 .init_count = ARRAY_SIZE(g12a_hifi_init_regs),
278 .flags = CLK_MESON_PLL_ROUND_CLOSEST,
279 },
280 .hw.init = &(struct clk_init_data){
281 .name = "hifi_pll_dco",
282 .ops = &meson_clk_pll_ops,
283 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
284 .num_parents = 1,
285 },
286};
287
288static struct clk_regmap g12a_hifi_pll = {
289 .data = &(struct clk_regmap_div_data){
290 .offset = HHI_HIFI_PLL_CNTL0,
291 .shift = 16,
292 .width = 2,
293 .flags = (CLK_DIVIDER_POWER_OF_TWO |
294 CLK_DIVIDER_ROUND_CLOSEST),
295 },
296 .hw.init = &(struct clk_init_data){
297 .name = "hifi_pll",
298 .ops = &clk_regmap_divider_ops,
299 .parent_names = (const char *[]){ "hifi_pll_dco" },
300 .num_parents = 1,
301 .flags = CLK_SET_RATE_PARENT,
302 },
303};
304
305static struct clk_regmap g12a_hdmi_pll_dco = {
306 .data = &(struct meson_clk_pll_data){
307 .en = {
308 .reg_off = HHI_HDMI_PLL_CNTL0,
309 .shift = 28,
310 .width = 1,
311 },
312 .m = {
313 .reg_off = HHI_HDMI_PLL_CNTL0,
314 .shift = 0,
315 .width = 8,
316 },
317 .n = {
318 .reg_off = HHI_HDMI_PLL_CNTL0,
319 .shift = 10,
320 .width = 5,
321 },
322 .frac = {
323 .reg_off = HHI_HDMI_PLL_CNTL1,
324 .shift = 0,
325 .width = 16,
326 },
327 .l = {
328 .reg_off = HHI_HDMI_PLL_CNTL0,
329 .shift = 30,
330 .width = 1,
331 },
332 .rst = {
333 .reg_off = HHI_HDMI_PLL_CNTL0,
334 .shift = 29,
335 .width = 1,
336 },
337 },
338 .hw.init = &(struct clk_init_data){
339 .name = "hdmi_pll_dco",
340 .ops = &meson_clk_pll_ro_ops,
341 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
342 .num_parents = 1,
343 /*
344 * Display directly handle hdmi pll registers ATM, we need
345 * NOCACHE to keep our view of the clock as accurate as possible
346 */
347 .flags = CLK_GET_RATE_NOCACHE,
348 },
349};
350
351static struct clk_regmap g12a_hdmi_pll_od = {
352 .data = &(struct clk_regmap_div_data){
353 .offset = HHI_HDMI_PLL_CNTL0,
354 .shift = 16,
355 .width = 2,
356 .flags = CLK_DIVIDER_POWER_OF_TWO,
357 },
358 .hw.init = &(struct clk_init_data){
359 .name = "hdmi_pll_od",
360 .ops = &clk_regmap_divider_ro_ops,
361 .parent_names = (const char *[]){ "hdmi_pll_dco" },
362 .num_parents = 1,
363 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
364 },
365};
366
367static struct clk_regmap g12a_hdmi_pll_od2 = {
368 .data = &(struct clk_regmap_div_data){
369 .offset = HHI_HDMI_PLL_CNTL0,
370 .shift = 18,
371 .width = 2,
372 .flags = CLK_DIVIDER_POWER_OF_TWO,
373 },
374 .hw.init = &(struct clk_init_data){
375 .name = "hdmi_pll_od2",
376 .ops = &clk_regmap_divider_ro_ops,
377 .parent_names = (const char *[]){ "hdmi_pll_od" },
378 .num_parents = 1,
379 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
380 },
381};
382
383static struct clk_regmap g12a_hdmi_pll = {
384 .data = &(struct clk_regmap_div_data){
385 .offset = HHI_HDMI_PLL_CNTL0,
386 .shift = 20,
387 .width = 2,
388 .flags = CLK_DIVIDER_POWER_OF_TWO,
389 },
390 .hw.init = &(struct clk_init_data){
391 .name = "hdmi_pll",
392 .ops = &clk_regmap_divider_ro_ops,
393 .parent_names = (const char *[]){ "hdmi_pll_od2" },
394 .num_parents = 1,
395 .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
396 },
397};
398
399static struct clk_fixed_factor g12a_fclk_div2_div = {
400 .mult = 1,
401 .div = 2,
402 .hw.init = &(struct clk_init_data){
403 .name = "fclk_div2_div",
404 .ops = &clk_fixed_factor_ops,
405 .parent_names = (const char *[]){ "fixed_pll" },
406 .num_parents = 1,
407 },
408};
409
410static struct clk_regmap g12a_fclk_div2 = {
411 .data = &(struct clk_regmap_gate_data){
412 .offset = HHI_FIX_PLL_CNTL1,
413 .bit_idx = 24,
414 },
415 .hw.init = &(struct clk_init_data){
416 .name = "fclk_div2",
417 .ops = &clk_regmap_gate_ops,
418 .parent_names = (const char *[]){ "fclk_div2_div" },
419 .num_parents = 1,
420 },
421};
422
423static struct clk_fixed_factor g12a_fclk_div3_div = {
424 .mult = 1,
425 .div = 3,
426 .hw.init = &(struct clk_init_data){
427 .name = "fclk_div3_div",
428 .ops = &clk_fixed_factor_ops,
429 .parent_names = (const char *[]){ "fixed_pll" },
430 .num_parents = 1,
431 },
432};
433
434static struct clk_regmap g12a_fclk_div3 = {
435 .data = &(struct clk_regmap_gate_data){
436 .offset = HHI_FIX_PLL_CNTL1,
437 .bit_idx = 20,
438 },
439 .hw.init = &(struct clk_init_data){
440 .name = "fclk_div3",
441 .ops = &clk_regmap_gate_ops,
442 .parent_names = (const char *[]){ "fclk_div3_div" },
443 .num_parents = 1,
444 },
445};
446
447static struct clk_fixed_factor g12a_fclk_div4_div = {
448 .mult = 1,
449 .div = 4,
450 .hw.init = &(struct clk_init_data){
451 .name = "fclk_div4_div",
452 .ops = &clk_fixed_factor_ops,
453 .parent_names = (const char *[]){ "fixed_pll" },
454 .num_parents = 1,
455 },
456};
457
458static struct clk_regmap g12a_fclk_div4 = {
459 .data = &(struct clk_regmap_gate_data){
460 .offset = HHI_FIX_PLL_CNTL1,
461 .bit_idx = 21,
462 },
463 .hw.init = &(struct clk_init_data){
464 .name = "fclk_div4",
465 .ops = &clk_regmap_gate_ops,
466 .parent_names = (const char *[]){ "fclk_div4_div" },
467 .num_parents = 1,
468 },
469};
470
471static struct clk_fixed_factor g12a_fclk_div5_div = {
472 .mult = 1,
473 .div = 5,
474 .hw.init = &(struct clk_init_data){
475 .name = "fclk_div5_div",
476 .ops = &clk_fixed_factor_ops,
477 .parent_names = (const char *[]){ "fixed_pll" },
478 .num_parents = 1,
479 },
480};
481
482static struct clk_regmap g12a_fclk_div5 = {
483 .data = &(struct clk_regmap_gate_data){
484 .offset = HHI_FIX_PLL_CNTL1,
485 .bit_idx = 22,
486 },
487 .hw.init = &(struct clk_init_data){
488 .name = "fclk_div5",
489 .ops = &clk_regmap_gate_ops,
490 .parent_names = (const char *[]){ "fclk_div5_div" },
491 .num_parents = 1,
492 },
493};
494
495static struct clk_fixed_factor g12a_fclk_div7_div = {
496 .mult = 1,
497 .div = 7,
498 .hw.init = &(struct clk_init_data){
499 .name = "fclk_div7_div",
500 .ops = &clk_fixed_factor_ops,
501 .parent_names = (const char *[]){ "fixed_pll" },
502 .num_parents = 1,
503 },
504};
505
506static struct clk_regmap g12a_fclk_div7 = {
507 .data = &(struct clk_regmap_gate_data){
508 .offset = HHI_FIX_PLL_CNTL1,
509 .bit_idx = 23,
510 },
511 .hw.init = &(struct clk_init_data){
512 .name = "fclk_div7",
513 .ops = &clk_regmap_gate_ops,
514 .parent_names = (const char *[]){ "fclk_div7_div" },
515 .num_parents = 1,
516 },
517};
518
519static struct clk_fixed_factor g12a_fclk_div2p5_div = {
520 .mult = 1,
521 .div = 5,
522 .hw.init = &(struct clk_init_data){
523 .name = "fclk_div2p5_div",
524 .ops = &clk_fixed_factor_ops,
525 .parent_names = (const char *[]){ "fixed_pll_dco" },
526 .num_parents = 1,
527 },
528};
529
530static struct clk_regmap g12a_fclk_div2p5 = {
531 .data = &(struct clk_regmap_gate_data){
532 .offset = HHI_FIX_PLL_CNTL1,
533 .bit_idx = 25,
534 },
535 .hw.init = &(struct clk_init_data){
536 .name = "fclk_div2p5",
537 .ops = &clk_regmap_gate_ops,
538 .parent_names = (const char *[]){ "fclk_div2p5_div" },
539 .num_parents = 1,
540 },
541};
542
543static struct clk_fixed_factor g12a_mpll_50m_div = {
544 .mult = 1,
545 .div = 80,
546 .hw.init = &(struct clk_init_data){
547 .name = "mpll_50m_div",
548 .ops = &clk_fixed_factor_ops,
549 .parent_names = (const char *[]){ "fixed_pll_dco" },
550 .num_parents = 1,
551 },
552};
553
554static struct clk_regmap g12a_mpll_50m = {
555 .data = &(struct clk_regmap_mux_data){
556 .offset = HHI_FIX_PLL_CNTL3,
557 .mask = 0x1,
558 .shift = 5,
559 },
560 .hw.init = &(struct clk_init_data){
561 .name = "mpll_50m",
562 .ops = &clk_regmap_mux_ro_ops,
563 .parent_names = (const char *[]){ IN_PREFIX "xtal",
564 "mpll_50m_div" },
565 .num_parents = 2,
566 },
567};
568
569static struct clk_fixed_factor g12a_mpll_prediv = {
570 .mult = 1,
571 .div = 2,
572 .hw.init = &(struct clk_init_data){
573 .name = "mpll_prediv",
574 .ops = &clk_fixed_factor_ops,
575 .parent_names = (const char *[]){ "fixed_pll_dco" },
576 .num_parents = 1,
577 },
578};
579
580static struct clk_regmap g12a_mpll0_div = {
581 .data = &(struct meson_clk_mpll_data){
582 .sdm = {
583 .reg_off = HHI_MPLL_CNTL1,
584 .shift = 0,
585 .width = 14,
586 },
587 .sdm_en = {
588 .reg_off = HHI_MPLL_CNTL1,
589 .shift = 30,
590 .width = 1,
591 },
592 .n2 = {
593 .reg_off = HHI_MPLL_CNTL1,
594 .shift = 20,
595 .width = 9,
596 },
597 .ssen = {
598 .reg_off = HHI_MPLL_CNTL1,
599 .shift = 29,
600 .width = 1,
601 },
602 .lock = &meson_clk_lock,
603 },
604 .hw.init = &(struct clk_init_data){
605 .name = "mpll0_div",
606 .ops = &meson_clk_mpll_ops,
607 .parent_names = (const char *[]){ "mpll_prediv" },
608 .num_parents = 1,
609 },
610};
611
612static struct clk_regmap g12a_mpll0 = {
613 .data = &(struct clk_regmap_gate_data){
614 .offset = HHI_MPLL_CNTL1,
615 .bit_idx = 31,
616 },
617 .hw.init = &(struct clk_init_data){
618 .name = "mpll0",
619 .ops = &clk_regmap_gate_ops,
620 .parent_names = (const char *[]){ "mpll0_div" },
621 .num_parents = 1,
622 .flags = CLK_SET_RATE_PARENT,
623 },
624};
625
626static struct clk_regmap g12a_mpll1_div = {
627 .data = &(struct meson_clk_mpll_data){
628 .sdm = {
629 .reg_off = HHI_MPLL_CNTL3,
630 .shift = 0,
631 .width = 14,
632 },
633 .sdm_en = {
634 .reg_off = HHI_MPLL_CNTL3,
635 .shift = 30,
636 .width = 1,
637 },
638 .n2 = {
639 .reg_off = HHI_MPLL_CNTL3,
640 .shift = 20,
641 .width = 9,
642 },
643 .ssen = {
644 .reg_off = HHI_MPLL_CNTL3,
645 .shift = 29,
646 .width = 1,
647 },
648 .lock = &meson_clk_lock,
649 },
650 .hw.init = &(struct clk_init_data){
651 .name = "mpll1_div",
652 .ops = &meson_clk_mpll_ops,
653 .parent_names = (const char *[]){ "mpll_prediv" },
654 .num_parents = 1,
655 },
656};
657
658static struct clk_regmap g12a_mpll1 = {
659 .data = &(struct clk_regmap_gate_data){
660 .offset = HHI_MPLL_CNTL3,
661 .bit_idx = 31,
662 },
663 .hw.init = &(struct clk_init_data){
664 .name = "mpll1",
665 .ops = &clk_regmap_gate_ops,
666 .parent_names = (const char *[]){ "mpll1_div" },
667 .num_parents = 1,
668 .flags = CLK_SET_RATE_PARENT,
669 },
670};
671
672static struct clk_regmap g12a_mpll2_div = {
673 .data = &(struct meson_clk_mpll_data){
674 .sdm = {
675 .reg_off = HHI_MPLL_CNTL5,
676 .shift = 0,
677 .width = 14,
678 },
679 .sdm_en = {
680 .reg_off = HHI_MPLL_CNTL5,
681 .shift = 30,
682 .width = 1,
683 },
684 .n2 = {
685 .reg_off = HHI_MPLL_CNTL5,
686 .shift = 20,
687 .width = 9,
688 },
689 .ssen = {
690 .reg_off = HHI_MPLL_CNTL5,
691 .shift = 29,
692 .width = 1,
693 },
694 .lock = &meson_clk_lock,
695 },
696 .hw.init = &(struct clk_init_data){
697 .name = "mpll2_div",
698 .ops = &meson_clk_mpll_ops,
699 .parent_names = (const char *[]){ "mpll_prediv" },
700 .num_parents = 1,
701 },
702};
703
704static struct clk_regmap g12a_mpll2 = {
705 .data = &(struct clk_regmap_gate_data){
706 .offset = HHI_MPLL_CNTL5,
707 .bit_idx = 31,
708 },
709 .hw.init = &(struct clk_init_data){
710 .name = "mpll2",
711 .ops = &clk_regmap_gate_ops,
712 .parent_names = (const char *[]){ "mpll2_div" },
713 .num_parents = 1,
714 .flags = CLK_SET_RATE_PARENT,
715 },
716};
717
718static struct clk_regmap g12a_mpll3_div = {
719 .data = &(struct meson_clk_mpll_data){
720 .sdm = {
721 .reg_off = HHI_MPLL_CNTL7,
722 .shift = 0,
723 .width = 14,
724 },
725 .sdm_en = {
726 .reg_off = HHI_MPLL_CNTL7,
727 .shift = 30,
728 .width = 1,
729 },
730 .n2 = {
731 .reg_off = HHI_MPLL_CNTL7,
732 .shift = 20,
733 .width = 9,
734 },
735 .ssen = {
736 .reg_off = HHI_MPLL_CNTL7,
737 .shift = 29,
738 .width = 1,
739 },
740 .lock = &meson_clk_lock,
741 },
742 .hw.init = &(struct clk_init_data){
743 .name = "mpll3_div",
744 .ops = &meson_clk_mpll_ops,
745 .parent_names = (const char *[]){ "mpll_prediv" },
746 .num_parents = 1,
747 },
748};
749
750static struct clk_regmap g12a_mpll3 = {
751 .data = &(struct clk_regmap_gate_data){
752 .offset = HHI_MPLL_CNTL7,
753 .bit_idx = 31,
754 },
755 .hw.init = &(struct clk_init_data){
756 .name = "mpll3",
757 .ops = &clk_regmap_gate_ops,
758 .parent_names = (const char *[]){ "mpll3_div" },
759 .num_parents = 1,
760 .flags = CLK_SET_RATE_PARENT,
761 },
762};
763
764static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
765static const char * const clk81_parent_names[] = {
766 IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
767 "fclk_div3", "fclk_div5"
768};
769
770static struct clk_regmap g12a_mpeg_clk_sel = {
771 .data = &(struct clk_regmap_mux_data){
772 .offset = HHI_MPEG_CLK_CNTL,
773 .mask = 0x7,
774 .shift = 12,
775 .table = mux_table_clk81,
776 },
777 .hw.init = &(struct clk_init_data){
778 .name = "mpeg_clk_sel",
779 .ops = &clk_regmap_mux_ro_ops,
780 .parent_names = clk81_parent_names,
781 .num_parents = ARRAY_SIZE(clk81_parent_names),
782 },
783};
784
785static struct clk_regmap g12a_mpeg_clk_div = {
786 .data = &(struct clk_regmap_div_data){
787 .offset = HHI_MPEG_CLK_CNTL,
788 .shift = 0,
789 .width = 7,
790 },
791 .hw.init = &(struct clk_init_data){
792 .name = "mpeg_clk_div",
793 .ops = &clk_regmap_divider_ops,
794 .parent_names = (const char *[]){ "mpeg_clk_sel" },
795 .num_parents = 1,
796 .flags = CLK_SET_RATE_PARENT,
797 },
798};
799
800static struct clk_regmap g12a_clk81 = {
801 .data = &(struct clk_regmap_gate_data){
802 .offset = HHI_MPEG_CLK_CNTL,
803 .bit_idx = 7,
804 },
805 .hw.init = &(struct clk_init_data){
806 .name = "clk81",
807 .ops = &clk_regmap_gate_ops,
808 .parent_names = (const char *[]){ "mpeg_clk_div" },
809 .num_parents = 1,
810 .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
811 },
812};
813
814static const char * const g12a_sd_emmc_clk0_parent_names[] = {
815 IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
816
817 /*
818 * Following these parent clocks, we should also have had mpll2, mpll3
819 * and gp0_pll but these clocks are too precious to be used here. All
820 * the necessary rates for MMC and NAND operation can be acheived using
821 * g12a_ee_core or fclk_div clocks
822 */
823};
824
825/* SDIO clock */
826static struct clk_regmap g12a_sd_emmc_a_clk0_sel = {
827 .data = &(struct clk_regmap_mux_data){
828 .offset = HHI_SD_EMMC_CLK_CNTL,
829 .mask = 0x7,
830 .shift = 9,
831 },
832 .hw.init = &(struct clk_init_data) {
833 .name = "sd_emmc_a_clk0_sel",
834 .ops = &clk_regmap_mux_ops,
835 .parent_names = g12a_sd_emmc_clk0_parent_names,
836 .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
837 .flags = CLK_SET_RATE_PARENT,
838 },
839};
840
841static struct clk_regmap g12a_sd_emmc_a_clk0_div = {
842 .data = &(struct clk_regmap_div_data){
843 .offset = HHI_SD_EMMC_CLK_CNTL,
844 .shift = 0,
845 .width = 7,
846 },
847 .hw.init = &(struct clk_init_data) {
848 .name = "sd_emmc_a_clk0_div",
849 .ops = &clk_regmap_divider_ops,
850 .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
851 .num_parents = 1,
852 .flags = CLK_SET_RATE_PARENT,
853 },
854};
855
856static struct clk_regmap g12a_sd_emmc_a_clk0 = {
857 .data = &(struct clk_regmap_gate_data){
858 .offset = HHI_SD_EMMC_CLK_CNTL,
859 .bit_idx = 7,
860 },
861 .hw.init = &(struct clk_init_data){
862 .name = "sd_emmc_a_clk0",
863 .ops = &clk_regmap_gate_ops,
864 .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
865 .num_parents = 1,
866 .flags = CLK_SET_RATE_PARENT,
867 },
868};
869
870/* SDcard clock */
871static struct clk_regmap g12a_sd_emmc_b_clk0_sel = {
872 .data = &(struct clk_regmap_mux_data){
873 .offset = HHI_SD_EMMC_CLK_CNTL,
874 .mask = 0x7,
875 .shift = 25,
876 },
877 .hw.init = &(struct clk_init_data) {
878 .name = "sd_emmc_b_clk0_sel",
879 .ops = &clk_regmap_mux_ops,
880 .parent_names = g12a_sd_emmc_clk0_parent_names,
881 .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
882 .flags = CLK_SET_RATE_PARENT,
883 },
884};
885
886static struct clk_regmap g12a_sd_emmc_b_clk0_div = {
887 .data = &(struct clk_regmap_div_data){
888 .offset = HHI_SD_EMMC_CLK_CNTL,
889 .shift = 16,
890 .width = 7,
891 },
892 .hw.init = &(struct clk_init_data) {
893 .name = "sd_emmc_b_clk0_div",
894 .ops = &clk_regmap_divider_ops,
895 .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
896 .num_parents = 1,
897 .flags = CLK_SET_RATE_PARENT,
898 },
899};
900
901static struct clk_regmap g12a_sd_emmc_b_clk0 = {
902 .data = &(struct clk_regmap_gate_data){
903 .offset = HHI_SD_EMMC_CLK_CNTL,
904 .bit_idx = 23,
905 },
906 .hw.init = &(struct clk_init_data){
907 .name = "sd_emmc_b_clk0",
908 .ops = &clk_regmap_gate_ops,
909 .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
910 .num_parents = 1,
911 .flags = CLK_SET_RATE_PARENT,
912 },
913};
914
915/* EMMC/NAND clock */
916static struct clk_regmap g12a_sd_emmc_c_clk0_sel = {
917 .data = &(struct clk_regmap_mux_data){
918 .offset = HHI_NAND_CLK_CNTL,
919 .mask = 0x7,
920 .shift = 9,
921 },
922 .hw.init = &(struct clk_init_data) {
923 .name = "sd_emmc_c_clk0_sel",
924 .ops = &clk_regmap_mux_ops,
925 .parent_names = g12a_sd_emmc_clk0_parent_names,
926 .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
927 .flags = CLK_SET_RATE_PARENT,
928 },
929};
930
931static struct clk_regmap g12a_sd_emmc_c_clk0_div = {
932 .data = &(struct clk_regmap_div_data){
933 .offset = HHI_NAND_CLK_CNTL,
934 .shift = 0,
935 .width = 7,
936 },
937 .hw.init = &(struct clk_init_data) {
938 .name = "sd_emmc_c_clk0_div",
939 .ops = &clk_regmap_divider_ops,
940 .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
941 .num_parents = 1,
942 .flags = CLK_SET_RATE_PARENT,
943 },
944};
945
946static struct clk_regmap g12a_sd_emmc_c_clk0 = {
947 .data = &(struct clk_regmap_gate_data){
948 .offset = HHI_NAND_CLK_CNTL,
949 .bit_idx = 7,
950 },
951 .hw.init = &(struct clk_init_data){
952 .name = "sd_emmc_c_clk0",
953 .ops = &clk_regmap_gate_ops,
954 .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
955 .num_parents = 1,
956 .flags = CLK_SET_RATE_PARENT,
957 },
958};
959
960/* VPU Clock */
961
962static const char * const g12a_vpu_parent_names[] = {
963 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
964 "mpll1", "vid_pll", "hifi_pll", "gp0_pll",
965};
966
967static struct clk_regmap g12a_vpu_0_sel = {
968 .data = &(struct clk_regmap_mux_data){
969 .offset = HHI_VPU_CLK_CNTL,
970 .mask = 0x3,
971 .shift = 9,
972 },
973 .hw.init = &(struct clk_init_data){
974 .name = "vpu_0_sel",
975 .ops = &clk_regmap_mux_ops,
976 .parent_names = g12a_vpu_parent_names,
977 .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
978 .flags = CLK_SET_RATE_NO_REPARENT,
979 },
980};
981
982static struct clk_regmap g12a_vpu_0_div = {
983 .data = &(struct clk_regmap_div_data){
984 .offset = HHI_VPU_CLK_CNTL,
985 .shift = 0,
986 .width = 7,
987 },
988 .hw.init = &(struct clk_init_data){
989 .name = "vpu_0_div",
990 .ops = &clk_regmap_divider_ops,
991 .parent_names = (const char *[]){ "vpu_0_sel" },
992 .num_parents = 1,
993 .flags = CLK_SET_RATE_PARENT,
994 },
995};
996
997static struct clk_regmap g12a_vpu_0 = {
998 .data = &(struct clk_regmap_gate_data){
999 .offset = HHI_VPU_CLK_CNTL,
1000 .bit_idx = 8,
1001 },
1002 .hw.init = &(struct clk_init_data) {
1003 .name = "vpu_0",
1004 .ops = &clk_regmap_gate_ops,
1005 .parent_names = (const char *[]){ "vpu_0_div" },
1006 .num_parents = 1,
1007 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1008 },
1009};
1010
1011static struct clk_regmap g12a_vpu_1_sel = {
1012 .data = &(struct clk_regmap_mux_data){
1013 .offset = HHI_VPU_CLK_CNTL,
1014 .mask = 0x3,
1015 .shift = 25,
1016 },
1017 .hw.init = &(struct clk_init_data){
1018 .name = "vpu_1_sel",
1019 .ops = &clk_regmap_mux_ops,
1020 .parent_names = g12a_vpu_parent_names,
1021 .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
1022 .flags = CLK_SET_RATE_NO_REPARENT,
1023 },
1024};
1025
1026static struct clk_regmap g12a_vpu_1_div = {
1027 .data = &(struct clk_regmap_div_data){
1028 .offset = HHI_VPU_CLK_CNTL,
1029 .shift = 16,
1030 .width = 7,
1031 },
1032 .hw.init = &(struct clk_init_data){
1033 .name = "vpu_1_div",
1034 .ops = &clk_regmap_divider_ops,
1035 .parent_names = (const char *[]){ "vpu_1_sel" },
1036 .num_parents = 1,
1037 .flags = CLK_SET_RATE_PARENT,
1038 },
1039};
1040
1041static struct clk_regmap g12a_vpu_1 = {
1042 .data = &(struct clk_regmap_gate_data){
1043 .offset = HHI_VPU_CLK_CNTL,
1044 .bit_idx = 24,
1045 },
1046 .hw.init = &(struct clk_init_data) {
1047 .name = "vpu_1",
1048 .ops = &clk_regmap_gate_ops,
1049 .parent_names = (const char *[]){ "vpu_1_div" },
1050 .num_parents = 1,
1051 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1052 },
1053};
1054
1055static struct clk_regmap g12a_vpu = {
1056 .data = &(struct clk_regmap_mux_data){
1057 .offset = HHI_VPU_CLK_CNTL,
1058 .mask = 1,
1059 .shift = 31,
1060 },
1061 .hw.init = &(struct clk_init_data){
1062 .name = "vpu",
1063 .ops = &clk_regmap_mux_ops,
1064 /*
1065 * bit 31 selects from 2 possible parents:
1066 * vpu_0 or vpu_1
1067 */
1068 .parent_names = (const char *[]){ "vpu_0", "vpu_1" },
1069 .num_parents = 2,
1070 .flags = CLK_SET_RATE_NO_REPARENT,
1071 },
1072};
1073
1074/* VAPB Clock */
1075
1076static const char * const g12a_vapb_parent_names[] = {
1077 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
1078 "mpll1", "vid_pll", "mpll2", "fclk_div2p5",
1079};
1080
1081static struct clk_regmap g12a_vapb_0_sel = {
1082 .data = &(struct clk_regmap_mux_data){
1083 .offset = HHI_VAPBCLK_CNTL,
1084 .mask = 0x3,
1085 .shift = 9,
1086 },
1087 .hw.init = &(struct clk_init_data){
1088 .name = "vapb_0_sel",
1089 .ops = &clk_regmap_mux_ops,
1090 .parent_names = g12a_vapb_parent_names,
1091 .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
1092 .flags = CLK_SET_RATE_NO_REPARENT,
1093 },
1094};
1095
1096static struct clk_regmap g12a_vapb_0_div = {
1097 .data = &(struct clk_regmap_div_data){
1098 .offset = HHI_VAPBCLK_CNTL,
1099 .shift = 0,
1100 .width = 7,
1101 },
1102 .hw.init = &(struct clk_init_data){
1103 .name = "vapb_0_div",
1104 .ops = &clk_regmap_divider_ops,
1105 .parent_names = (const char *[]){ "vapb_0_sel" },
1106 .num_parents = 1,
1107 .flags = CLK_SET_RATE_PARENT,
1108 },
1109};
1110
1111static struct clk_regmap g12a_vapb_0 = {
1112 .data = &(struct clk_regmap_gate_data){
1113 .offset = HHI_VAPBCLK_CNTL,
1114 .bit_idx = 8,
1115 },
1116 .hw.init = &(struct clk_init_data) {
1117 .name = "vapb_0",
1118 .ops = &clk_regmap_gate_ops,
1119 .parent_names = (const char *[]){ "vapb_0_div" },
1120 .num_parents = 1,
1121 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1122 },
1123};
1124
1125static struct clk_regmap g12a_vapb_1_sel = {
1126 .data = &(struct clk_regmap_mux_data){
1127 .offset = HHI_VAPBCLK_CNTL,
1128 .mask = 0x3,
1129 .shift = 25,
1130 },
1131 .hw.init = &(struct clk_init_data){
1132 .name = "vapb_1_sel",
1133 .ops = &clk_regmap_mux_ops,
1134 .parent_names = g12a_vapb_parent_names,
1135 .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
1136 .flags = CLK_SET_RATE_NO_REPARENT,
1137 },
1138};
1139
1140static struct clk_regmap g12a_vapb_1_div = {
1141 .data = &(struct clk_regmap_div_data){
1142 .offset = HHI_VAPBCLK_CNTL,
1143 .shift = 16,
1144 .width = 7,
1145 },
1146 .hw.init = &(struct clk_init_data){
1147 .name = "vapb_1_div",
1148 .ops = &clk_regmap_divider_ops,
1149 .parent_names = (const char *[]){ "vapb_1_sel" },
1150 .num_parents = 1,
1151 .flags = CLK_SET_RATE_PARENT,
1152 },
1153};
1154
1155static struct clk_regmap g12a_vapb_1 = {
1156 .data = &(struct clk_regmap_gate_data){
1157 .offset = HHI_VAPBCLK_CNTL,
1158 .bit_idx = 24,
1159 },
1160 .hw.init = &(struct clk_init_data) {
1161 .name = "vapb_1",
1162 .ops = &clk_regmap_gate_ops,
1163 .parent_names = (const char *[]){ "vapb_1_div" },
1164 .num_parents = 1,
1165 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1166 },
1167};
1168
1169static struct clk_regmap g12a_vapb_sel = {
1170 .data = &(struct clk_regmap_mux_data){
1171 .offset = HHI_VAPBCLK_CNTL,
1172 .mask = 1,
1173 .shift = 31,
1174 },
1175 .hw.init = &(struct clk_init_data){
1176 .name = "vapb_sel",
1177 .ops = &clk_regmap_mux_ops,
1178 /*
1179 * bit 31 selects from 2 possible parents:
1180 * vapb_0 or vapb_1
1181 */
1182 .parent_names = (const char *[]){ "vapb_0", "vapb_1" },
1183 .num_parents = 2,
1184 .flags = CLK_SET_RATE_NO_REPARENT,
1185 },
1186};
1187
1188static struct clk_regmap g12a_vapb = {
1189 .data = &(struct clk_regmap_gate_data){
1190 .offset = HHI_VAPBCLK_CNTL,
1191 .bit_idx = 30,
1192 },
1193 .hw.init = &(struct clk_init_data) {
1194 .name = "vapb",
1195 .ops = &clk_regmap_gate_ops,
1196 .parent_names = (const char *[]){ "vapb_sel" },
1197 .num_parents = 1,
1198 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1199 },
1200};
1201
1202/* Video Clocks */
1203
1204static struct clk_regmap g12a_vid_pll_div = {
1205 .data = &(struct meson_vid_pll_div_data){
1206 .val = {
1207 .reg_off = HHI_VID_PLL_CLK_DIV,
1208 .shift = 0,
1209 .width = 15,
1210 },
1211 .sel = {
1212 .reg_off = HHI_VID_PLL_CLK_DIV,
1213 .shift = 16,
1214 .width = 2,
1215 },
1216 },
1217 .hw.init = &(struct clk_init_data) {
1218 .name = "vid_pll_div",
1219 .ops = &meson_vid_pll_div_ro_ops,
1220 .parent_names = (const char *[]){ "hdmi_pll" },
1221 .num_parents = 1,
1222 .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
1223 },
1224};
1225
1226static const char * const g12a_vid_pll_parent_names[] = { "vid_pll_div",
1227 "hdmi_pll" };
1228
1229static struct clk_regmap g12a_vid_pll_sel = {
1230 .data = &(struct clk_regmap_mux_data){
1231 .offset = HHI_VID_PLL_CLK_DIV,
1232 .mask = 0x1,
1233 .shift = 18,
1234 },
1235 .hw.init = &(struct clk_init_data){
1236 .name = "vid_pll_sel",
1237 .ops = &clk_regmap_mux_ops,
1238 /*
1239 * bit 18 selects from 2 possible parents:
1240 * vid_pll_div or hdmi_pll
1241 */
1242 .parent_names = g12a_vid_pll_parent_names,
1243 .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_names),
1244 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1245 },
1246};
1247
1248static struct clk_regmap g12a_vid_pll = {
1249 .data = &(struct clk_regmap_gate_data){
1250 .offset = HHI_VID_PLL_CLK_DIV,
1251 .bit_idx = 19,
1252 },
1253 .hw.init = &(struct clk_init_data) {
1254 .name = "vid_pll",
1255 .ops = &clk_regmap_gate_ops,
1256 .parent_names = (const char *[]){ "vid_pll_sel" },
1257 .num_parents = 1,
1258 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1259 },
1260};
1261
1262static const char * const g12a_vclk_parent_names[] = {
1263 "vid_pll", "gp0_pll", "hifi_pll", "mpll1", "fclk_div3", "fclk_div4",
1264 "fclk_div5", "fclk_div7"
1265};
1266
1267static struct clk_regmap g12a_vclk_sel = {
1268 .data = &(struct clk_regmap_mux_data){
1269 .offset = HHI_VID_CLK_CNTL,
1270 .mask = 0x7,
1271 .shift = 16,
1272 },
1273 .hw.init = &(struct clk_init_data){
1274 .name = "vclk_sel",
1275 .ops = &clk_regmap_mux_ops,
1276 .parent_names = g12a_vclk_parent_names,
1277 .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
1278 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1279 },
1280};
1281
1282static struct clk_regmap g12a_vclk2_sel = {
1283 .data = &(struct clk_regmap_mux_data){
1284 .offset = HHI_VIID_CLK_CNTL,
1285 .mask = 0x7,
1286 .shift = 16,
1287 },
1288 .hw.init = &(struct clk_init_data){
1289 .name = "vclk2_sel",
1290 .ops = &clk_regmap_mux_ops,
1291 .parent_names = g12a_vclk_parent_names,
1292 .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
1293 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1294 },
1295};
1296
1297static struct clk_regmap g12a_vclk_input = {
1298 .data = &(struct clk_regmap_gate_data){
1299 .offset = HHI_VID_CLK_DIV,
1300 .bit_idx = 16,
1301 },
1302 .hw.init = &(struct clk_init_data) {
1303 .name = "vclk_input",
1304 .ops = &clk_regmap_gate_ops,
1305 .parent_names = (const char *[]){ "vclk_sel" },
1306 .num_parents = 1,
1307 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1308 },
1309};
1310
1311static struct clk_regmap g12a_vclk2_input = {
1312 .data = &(struct clk_regmap_gate_data){
1313 .offset = HHI_VIID_CLK_DIV,
1314 .bit_idx = 16,
1315 },
1316 .hw.init = &(struct clk_init_data) {
1317 .name = "vclk2_input",
1318 .ops = &clk_regmap_gate_ops,
1319 .parent_names = (const char *[]){ "vclk2_sel" },
1320 .num_parents = 1,
1321 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1322 },
1323};
1324
1325static struct clk_regmap g12a_vclk_div = {
1326 .data = &(struct clk_regmap_div_data){
1327 .offset = HHI_VID_CLK_DIV,
1328 .shift = 0,
1329 .width = 8,
1330 },
1331 .hw.init = &(struct clk_init_data){
1332 .name = "vclk_div",
1333 .ops = &clk_regmap_divider_ops,
1334 .parent_names = (const char *[]){ "vclk_input" },
1335 .num_parents = 1,
1336 .flags = CLK_GET_RATE_NOCACHE,
1337 },
1338};
1339
1340static struct clk_regmap g12a_vclk2_div = {
1341 .data = &(struct clk_regmap_div_data){
1342 .offset = HHI_VIID_CLK_DIV,
1343 .shift = 0,
1344 .width = 8,
1345 },
1346 .hw.init = &(struct clk_init_data){
1347 .name = "vclk2_div",
1348 .ops = &clk_regmap_divider_ops,
1349 .parent_names = (const char *[]){ "vclk2_input" },
1350 .num_parents = 1,
1351 .flags = CLK_GET_RATE_NOCACHE,
1352 },
1353};
1354
1355static struct clk_regmap g12a_vclk = {
1356 .data = &(struct clk_regmap_gate_data){
1357 .offset = HHI_VID_CLK_CNTL,
1358 .bit_idx = 19,
1359 },
1360 .hw.init = &(struct clk_init_data) {
1361 .name = "vclk",
1362 .ops = &clk_regmap_gate_ops,
1363 .parent_names = (const char *[]){ "vclk_div" },
1364 .num_parents = 1,
1365 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1366 },
1367};
1368
1369static struct clk_regmap g12a_vclk2 = {
1370 .data = &(struct clk_regmap_gate_data){
1371 .offset = HHI_VIID_CLK_CNTL,
1372 .bit_idx = 19,
1373 },
1374 .hw.init = &(struct clk_init_data) {
1375 .name = "vclk2",
1376 .ops = &clk_regmap_gate_ops,
1377 .parent_names = (const char *[]){ "vclk2_div" },
1378 .num_parents = 1,
1379 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1380 },
1381};
1382
1383static struct clk_regmap g12a_vclk_div1 = {
1384 .data = &(struct clk_regmap_gate_data){
1385 .offset = HHI_VID_CLK_CNTL,
1386 .bit_idx = 0,
1387 },
1388 .hw.init = &(struct clk_init_data) {
1389 .name = "vclk_div1",
1390 .ops = &clk_regmap_gate_ops,
1391 .parent_names = (const char *[]){ "vclk" },
1392 .num_parents = 1,
1393 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1394 },
1395};
1396
1397static struct clk_regmap g12a_vclk_div2_en = {
1398 .data = &(struct clk_regmap_gate_data){
1399 .offset = HHI_VID_CLK_CNTL,
1400 .bit_idx = 1,
1401 },
1402 .hw.init = &(struct clk_init_data) {
1403 .name = "vclk_div2_en",
1404 .ops = &clk_regmap_gate_ops,
1405 .parent_names = (const char *[]){ "vclk" },
1406 .num_parents = 1,
1407 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1408 },
1409};
1410
1411static struct clk_regmap g12a_vclk_div4_en = {
1412 .data = &(struct clk_regmap_gate_data){
1413 .offset = HHI_VID_CLK_CNTL,
1414 .bit_idx = 2,
1415 },
1416 .hw.init = &(struct clk_init_data) {
1417 .name = "vclk_div4_en",
1418 .ops = &clk_regmap_gate_ops,
1419 .parent_names = (const char *[]){ "vclk" },
1420 .num_parents = 1,
1421 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1422 },
1423};
1424
1425static struct clk_regmap g12a_vclk_div6_en = {
1426 .data = &(struct clk_regmap_gate_data){
1427 .offset = HHI_VID_CLK_CNTL,
1428 .bit_idx = 3,
1429 },
1430 .hw.init = &(struct clk_init_data) {
1431 .name = "vclk_div6_en",
1432 .ops = &clk_regmap_gate_ops,
1433 .parent_names = (const char *[]){ "vclk" },
1434 .num_parents = 1,
1435 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1436 },
1437};
1438
1439static struct clk_regmap g12a_vclk_div12_en = {
1440 .data = &(struct clk_regmap_gate_data){
1441 .offset = HHI_VID_CLK_CNTL,
1442 .bit_idx = 4,
1443 },
1444 .hw.init = &(struct clk_init_data) {
1445 .name = "vclk_div12_en",
1446 .ops = &clk_regmap_gate_ops,
1447 .parent_names = (const char *[]){ "vclk" },
1448 .num_parents = 1,
1449 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1450 },
1451};
1452
1453static struct clk_regmap g12a_vclk2_div1 = {
1454 .data = &(struct clk_regmap_gate_data){
1455 .offset = HHI_VIID_CLK_CNTL,
1456 .bit_idx = 0,
1457 },
1458 .hw.init = &(struct clk_init_data) {
1459 .name = "vclk2_div1",
1460 .ops = &clk_regmap_gate_ops,
1461 .parent_names = (const char *[]){ "vclk2" },
1462 .num_parents = 1,
1463 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1464 },
1465};
1466
1467static struct clk_regmap g12a_vclk2_div2_en = {
1468 .data = &(struct clk_regmap_gate_data){
1469 .offset = HHI_VIID_CLK_CNTL,
1470 .bit_idx = 1,
1471 },
1472 .hw.init = &(struct clk_init_data) {
1473 .name = "vclk2_div2_en",
1474 .ops = &clk_regmap_gate_ops,
1475 .parent_names = (const char *[]){ "vclk2" },
1476 .num_parents = 1,
1477 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1478 },
1479};
1480
1481static struct clk_regmap g12a_vclk2_div4_en = {
1482 .data = &(struct clk_regmap_gate_data){
1483 .offset = HHI_VIID_CLK_CNTL,
1484 .bit_idx = 2,
1485 },
1486 .hw.init = &(struct clk_init_data) {
1487 .name = "vclk2_div4_en",
1488 .ops = &clk_regmap_gate_ops,
1489 .parent_names = (const char *[]){ "vclk2" },
1490 .num_parents = 1,
1491 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1492 },
1493};
1494
1495static struct clk_regmap g12a_vclk2_div6_en = {
1496 .data = &(struct clk_regmap_gate_data){
1497 .offset = HHI_VIID_CLK_CNTL,
1498 .bit_idx = 3,
1499 },
1500 .hw.init = &(struct clk_init_data) {
1501 .name = "vclk2_div6_en",
1502 .ops = &clk_regmap_gate_ops,
1503 .parent_names = (const char *[]){ "vclk2" },
1504 .num_parents = 1,
1505 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1506 },
1507};
1508
1509static struct clk_regmap g12a_vclk2_div12_en = {
1510 .data = &(struct clk_regmap_gate_data){
1511 .offset = HHI_VIID_CLK_CNTL,
1512 .bit_idx = 4,
1513 },
1514 .hw.init = &(struct clk_init_data) {
1515 .name = "vclk2_div12_en",
1516 .ops = &clk_regmap_gate_ops,
1517 .parent_names = (const char *[]){ "vclk2" },
1518 .num_parents = 1,
1519 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1520 },
1521};
1522
1523static struct clk_fixed_factor g12a_vclk_div2 = {
1524 .mult = 1,
1525 .div = 2,
1526 .hw.init = &(struct clk_init_data){
1527 .name = "vclk_div2",
1528 .ops = &clk_fixed_factor_ops,
1529 .parent_names = (const char *[]){ "vclk_div2_en" },
1530 .num_parents = 1,
1531 },
1532};
1533
1534static struct clk_fixed_factor g12a_vclk_div4 = {
1535 .mult = 1,
1536 .div = 4,
1537 .hw.init = &(struct clk_init_data){
1538 .name = "vclk_div4",
1539 .ops = &clk_fixed_factor_ops,
1540 .parent_names = (const char *[]){ "vclk_div4_en" },
1541 .num_parents = 1,
1542 },
1543};
1544
1545static struct clk_fixed_factor g12a_vclk_div6 = {
1546 .mult = 1,
1547 .div = 6,
1548 .hw.init = &(struct clk_init_data){
1549 .name = "vclk_div6",
1550 .ops = &clk_fixed_factor_ops,
1551 .parent_names = (const char *[]){ "vclk_div6_en" },
1552 .num_parents = 1,
1553 },
1554};
1555
1556static struct clk_fixed_factor g12a_vclk_div12 = {
1557 .mult = 1,
1558 .div = 12,
1559 .hw.init = &(struct clk_init_data){
1560 .name = "vclk_div12",
1561 .ops = &clk_fixed_factor_ops,
1562 .parent_names = (const char *[]){ "vclk_div12_en" },
1563 .num_parents = 1,
1564 },
1565};
1566
1567static struct clk_fixed_factor g12a_vclk2_div2 = {
1568 .mult = 1,
1569 .div = 2,
1570 .hw.init = &(struct clk_init_data){
1571 .name = "vclk2_div2",
1572 .ops = &clk_fixed_factor_ops,
1573 .parent_names = (const char *[]){ "vclk2_div2_en" },
1574 .num_parents = 1,
1575 },
1576};
1577
1578static struct clk_fixed_factor g12a_vclk2_div4 = {
1579 .mult = 1,
1580 .div = 4,
1581 .hw.init = &(struct clk_init_data){
1582 .name = "vclk2_div4",
1583 .ops = &clk_fixed_factor_ops,
1584 .parent_names = (const char *[]){ "vclk2_div4_en" },
1585 .num_parents = 1,
1586 },
1587};
1588
1589static struct clk_fixed_factor g12a_vclk2_div6 = {
1590 .mult = 1,
1591 .div = 6,
1592 .hw.init = &(struct clk_init_data){
1593 .name = "vclk2_div6",
1594 .ops = &clk_fixed_factor_ops,
1595 .parent_names = (const char *[]){ "vclk2_div6_en" },
1596 .num_parents = 1,
1597 },
1598};
1599
1600static struct clk_fixed_factor g12a_vclk2_div12 = {
1601 .mult = 1,
1602 .div = 12,
1603 .hw.init = &(struct clk_init_data){
1604 .name = "vclk2_div12",
1605 .ops = &clk_fixed_factor_ops,
1606 .parent_names = (const char *[]){ "vclk2_div12_en" },
1607 .num_parents = 1,
1608 },
1609};
1610
1611static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
1612static const char * const g12a_cts_parent_names[] = {
1613 "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
1614 "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
1615 "vclk2_div6", "vclk2_div12"
1616};
1617
1618static struct clk_regmap g12a_cts_enci_sel = {
1619 .data = &(struct clk_regmap_mux_data){
1620 .offset = HHI_VID_CLK_DIV,
1621 .mask = 0xf,
1622 .shift = 28,
1623 .table = mux_table_cts_sel,
1624 },
1625 .hw.init = &(struct clk_init_data){
1626 .name = "cts_enci_sel",
1627 .ops = &clk_regmap_mux_ops,
1628 .parent_names = g12a_cts_parent_names,
1629 .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
1630 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1631 },
1632};
1633
1634static struct clk_regmap g12a_cts_encp_sel = {
1635 .data = &(struct clk_regmap_mux_data){
1636 .offset = HHI_VID_CLK_DIV,
1637 .mask = 0xf,
1638 .shift = 20,
1639 .table = mux_table_cts_sel,
1640 },
1641 .hw.init = &(struct clk_init_data){
1642 .name = "cts_encp_sel",
1643 .ops = &clk_regmap_mux_ops,
1644 .parent_names = g12a_cts_parent_names,
1645 .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
1646 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1647 },
1648};
1649
1650static struct clk_regmap g12a_cts_vdac_sel = {
1651 .data = &(struct clk_regmap_mux_data){
1652 .offset = HHI_VIID_CLK_DIV,
1653 .mask = 0xf,
1654 .shift = 28,
1655 .table = mux_table_cts_sel,
1656 },
1657 .hw.init = &(struct clk_init_data){
1658 .name = "cts_vdac_sel",
1659 .ops = &clk_regmap_mux_ops,
1660 .parent_names = g12a_cts_parent_names,
1661 .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
1662 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1663 },
1664};
1665
1666/* TOFIX: add support for cts_tcon */
1667static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
1668static const char * const g12a_cts_hdmi_tx_parent_names[] = {
1669 "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
1670 "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
1671 "vclk2_div6", "vclk2_div12"
1672};
1673
1674static struct clk_regmap g12a_hdmi_tx_sel = {
1675 .data = &(struct clk_regmap_mux_data){
1676 .offset = HHI_HDMI_CLK_CNTL,
1677 .mask = 0xf,
1678 .shift = 16,
1679 .table = mux_table_hdmi_tx_sel,
1680 },
1681 .hw.init = &(struct clk_init_data){
1682 .name = "hdmi_tx_sel",
1683 .ops = &clk_regmap_mux_ops,
1684 .parent_names = g12a_cts_hdmi_tx_parent_names,
1685 .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_names),
1686 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1687 },
1688};
1689
1690static struct clk_regmap g12a_cts_enci = {
1691 .data = &(struct clk_regmap_gate_data){
1692 .offset = HHI_VID_CLK_CNTL2,
1693 .bit_idx = 0,
1694 },
1695 .hw.init = &(struct clk_init_data) {
1696 .name = "cts_enci",
1697 .ops = &clk_regmap_gate_ops,
1698 .parent_names = (const char *[]){ "cts_enci_sel" },
1699 .num_parents = 1,
1700 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1701 },
1702};
1703
1704static struct clk_regmap g12a_cts_encp = {
1705 .data = &(struct clk_regmap_gate_data){
1706 .offset = HHI_VID_CLK_CNTL2,
1707 .bit_idx = 2,
1708 },
1709 .hw.init = &(struct clk_init_data) {
1710 .name = "cts_encp",
1711 .ops = &clk_regmap_gate_ops,
1712 .parent_names = (const char *[]){ "cts_encp_sel" },
1713 .num_parents = 1,
1714 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1715 },
1716};
1717
1718static struct clk_regmap g12a_cts_vdac = {
1719 .data = &(struct clk_regmap_gate_data){
1720 .offset = HHI_VID_CLK_CNTL2,
1721 .bit_idx = 4,
1722 },
1723 .hw.init = &(struct clk_init_data) {
1724 .name = "cts_vdac",
1725 .ops = &clk_regmap_gate_ops,
1726 .parent_names = (const char *[]){ "cts_vdac_sel" },
1727 .num_parents = 1,
1728 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1729 },
1730};
1731
1732static struct clk_regmap g12a_hdmi_tx = {
1733 .data = &(struct clk_regmap_gate_data){
1734 .offset = HHI_VID_CLK_CNTL2,
1735 .bit_idx = 5,
1736 },
1737 .hw.init = &(struct clk_init_data) {
1738 .name = "hdmi_tx",
1739 .ops = &clk_regmap_gate_ops,
1740 .parent_names = (const char *[]){ "hdmi_tx_sel" },
1741 .num_parents = 1,
1742 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1743 },
1744};
1745
1746/* HDMI Clocks */
1747
1748static const char * const g12a_hdmi_parent_names[] = {
1749 IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
1750};
1751
1752static struct clk_regmap g12a_hdmi_sel = {
1753 .data = &(struct clk_regmap_mux_data){
1754 .offset = HHI_HDMI_CLK_CNTL,
1755 .mask = 0x3,
1756 .shift = 9,
1757 .flags = CLK_MUX_ROUND_CLOSEST,
1758 },
1759 .hw.init = &(struct clk_init_data){
1760 .name = "hdmi_sel",
1761 .ops = &clk_regmap_mux_ops,
1762 .parent_names = g12a_hdmi_parent_names,
1763 .num_parents = ARRAY_SIZE(g12a_hdmi_parent_names),
1764 .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
1765 },
1766};
1767
1768static struct clk_regmap g12a_hdmi_div = {
1769 .data = &(struct clk_regmap_div_data){
1770 .offset = HHI_HDMI_CLK_CNTL,
1771 .shift = 0,
1772 .width = 7,
1773 },
1774 .hw.init = &(struct clk_init_data){
1775 .name = "hdmi_div",
1776 .ops = &clk_regmap_divider_ops,
1777 .parent_names = (const char *[]){ "hdmi_sel" },
1778 .num_parents = 1,
1779 .flags = CLK_GET_RATE_NOCACHE,
1780 },
1781};
1782
1783static struct clk_regmap g12a_hdmi = {
1784 .data = &(struct clk_regmap_gate_data){
1785 .offset = HHI_HDMI_CLK_CNTL,
1786 .bit_idx = 8,
1787 },
1788 .hw.init = &(struct clk_init_data) {
1789 .name = "hdmi",
1790 .ops = &clk_regmap_gate_ops,
1791 .parent_names = (const char *[]){ "hdmi_div" },
1792 .num_parents = 1,
1793 .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
1794 },
1795};
1796
1797/*
1798 * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
1799 * muxed by a glitch-free switch.
1800 */
1801
1802static const char * const g12a_mali_0_1_parent_names[] = {
1803 IN_PREFIX "xtal", "gp0_pll", "hihi_pll", "fclk_div2p5",
1804 "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7"
1805};
1806
1807static struct clk_regmap g12a_mali_0_sel = {
1808 .data = &(struct clk_regmap_mux_data){
1809 .offset = HHI_MALI_CLK_CNTL,
1810 .mask = 0x7,
1811 .shift = 9,
1812 },
1813 .hw.init = &(struct clk_init_data){
1814 .name = "mali_0_sel",
1815 .ops = &clk_regmap_mux_ops,
1816 .parent_names = g12a_mali_0_1_parent_names,
1817 .num_parents = 8,
1818 .flags = CLK_SET_RATE_NO_REPARENT,
1819 },
1820};
1821
1822static struct clk_regmap g12a_mali_0_div = {
1823 .data = &(struct clk_regmap_div_data){
1824 .offset = HHI_MALI_CLK_CNTL,
1825 .shift = 0,
1826 .width = 7,
1827 },
1828 .hw.init = &(struct clk_init_data){
1829 .name = "mali_0_div",
1830 .ops = &clk_regmap_divider_ops,
1831 .parent_names = (const char *[]){ "mali_0_sel" },
1832 .num_parents = 1,
1833 .flags = CLK_SET_RATE_NO_REPARENT,
1834 },
1835};
1836
1837static struct clk_regmap g12a_mali_0 = {
1838 .data = &(struct clk_regmap_gate_data){
1839 .offset = HHI_MALI_CLK_CNTL,
1840 .bit_idx = 8,
1841 },
1842 .hw.init = &(struct clk_init_data){
1843 .name = "mali_0",
1844 .ops = &clk_regmap_gate_ops,
1845 .parent_names = (const char *[]){ "mali_0_div" },
1846 .num_parents = 1,
1847 .flags = CLK_SET_RATE_PARENT,
1848 },
1849};
1850
1851static struct clk_regmap g12a_mali_1_sel = {
1852 .data = &(struct clk_regmap_mux_data){
1853 .offset = HHI_MALI_CLK_CNTL,
1854 .mask = 0x7,
1855 .shift = 25,
1856 },
1857 .hw.init = &(struct clk_init_data){
1858 .name = "mali_1_sel",
1859 .ops = &clk_regmap_mux_ops,
1860 .parent_names = g12a_mali_0_1_parent_names,
1861 .num_parents = 8,
1862 .flags = CLK_SET_RATE_NO_REPARENT,
1863 },
1864};
1865
1866static struct clk_regmap g12a_mali_1_div = {
1867 .data = &(struct clk_regmap_div_data){
1868 .offset = HHI_MALI_CLK_CNTL,
1869 .shift = 16,
1870 .width = 7,
1871 },
1872 .hw.init = &(struct clk_init_data){
1873 .name = "mali_1_div",
1874 .ops = &clk_regmap_divider_ops,
1875 .parent_names = (const char *[]){ "mali_1_sel" },
1876 .num_parents = 1,
1877 .flags = CLK_SET_RATE_NO_REPARENT,
1878 },
1879};
1880
1881static struct clk_regmap g12a_mali_1 = {
1882 .data = &(struct clk_regmap_gate_data){
1883 .offset = HHI_MALI_CLK_CNTL,
1884 .bit_idx = 24,
1885 },
1886 .hw.init = &(struct clk_init_data){
1887 .name = "mali_1",
1888 .ops = &clk_regmap_gate_ops,
1889 .parent_names = (const char *[]){ "mali_1_div" },
1890 .num_parents = 1,
1891 .flags = CLK_SET_RATE_PARENT,
1892 },
1893};
1894
1895static const char * const g12a_mali_parent_names[] = {
1896 "mali_0", "mali_1"
1897};
1898
1899static struct clk_regmap g12a_mali = {
1900 .data = &(struct clk_regmap_mux_data){
1901 .offset = HHI_MALI_CLK_CNTL,
1902 .mask = 1,
1903 .shift = 31,
1904 },
1905 .hw.init = &(struct clk_init_data){
1906 .name = "mali",
1907 .ops = &clk_regmap_mux_ops,
1908 .parent_names = g12a_mali_parent_names,
1909 .num_parents = 2,
1910 .flags = CLK_SET_RATE_NO_REPARENT,
1911 },
1912};
1913
1914/* Everything Else (EE) domain gates */
1915static MESON_GATE(g12a_ddr, HHI_GCLK_MPEG0, 0);
1916static MESON_GATE(g12a_dos, HHI_GCLK_MPEG0, 1);
1917static MESON_GATE(g12a_audio_locker, HHI_GCLK_MPEG0, 2);
1918static MESON_GATE(g12a_mipi_dsi_host, HHI_GCLK_MPEG0, 3);
1919static MESON_GATE(g12a_eth_phy, HHI_GCLK_MPEG0, 4);
1920static MESON_GATE(g12a_isa, HHI_GCLK_MPEG0, 5);
1921static MESON_GATE(g12a_pl301, HHI_GCLK_MPEG0, 6);
1922static MESON_GATE(g12a_periphs, HHI_GCLK_MPEG0, 7);
1923static MESON_GATE(g12a_spicc_0, HHI_GCLK_MPEG0, 8);
1924static MESON_GATE(g12a_i2c, HHI_GCLK_MPEG0, 9);
1925static MESON_GATE(g12a_sana, HHI_GCLK_MPEG0, 10);
1926static MESON_GATE(g12a_sd, HHI_GCLK_MPEG0, 11);
1927static MESON_GATE(g12a_rng0, HHI_GCLK_MPEG0, 12);
1928static MESON_GATE(g12a_uart0, HHI_GCLK_MPEG0, 13);
1929static MESON_GATE(g12a_spicc_1, HHI_GCLK_MPEG0, 14);
1930static MESON_GATE(g12a_hiu_reg, HHI_GCLK_MPEG0, 19);
1931static MESON_GATE(g12a_mipi_dsi_phy, HHI_GCLK_MPEG0, 20);
1932static MESON_GATE(g12a_assist_misc, HHI_GCLK_MPEG0, 23);
1933static MESON_GATE(g12a_emmc_a, HHI_GCLK_MPEG0, 4);
1934static MESON_GATE(g12a_emmc_b, HHI_GCLK_MPEG0, 25);
1935static MESON_GATE(g12a_emmc_c, HHI_GCLK_MPEG0, 26);
1936static MESON_GATE(g12a_audio_codec, HHI_GCLK_MPEG0, 28);
1937
1938static MESON_GATE(g12a_audio, HHI_GCLK_MPEG1, 0);
1939static MESON_GATE(g12a_eth_core, HHI_GCLK_MPEG1, 3);
1940static MESON_GATE(g12a_demux, HHI_GCLK_MPEG1, 4);
1941static MESON_GATE(g12a_audio_ififo, HHI_GCLK_MPEG1, 11);
1942static MESON_GATE(g12a_adc, HHI_GCLK_MPEG1, 13);
1943static MESON_GATE(g12a_uart1, HHI_GCLK_MPEG1, 16);
1944static MESON_GATE(g12a_g2d, HHI_GCLK_MPEG1, 20);
1945static MESON_GATE(g12a_reset, HHI_GCLK_MPEG1, 23);
1946static MESON_GATE(g12a_pcie_comb, HHI_GCLK_MPEG1, 24);
1947static MESON_GATE(g12a_parser, HHI_GCLK_MPEG1, 25);
1948static MESON_GATE(g12a_usb_general, HHI_GCLK_MPEG1, 26);
1949static MESON_GATE(g12a_pcie_phy, HHI_GCLK_MPEG1, 27);
1950static MESON_GATE(g12a_ahb_arb0, HHI_GCLK_MPEG1, 29);
1951
1952static MESON_GATE(g12a_ahb_data_bus, HHI_GCLK_MPEG2, 1);
1953static MESON_GATE(g12a_ahb_ctrl_bus, HHI_GCLK_MPEG2, 2);
1954static MESON_GATE(g12a_htx_hdcp22, HHI_GCLK_MPEG2, 3);
1955static MESON_GATE(g12a_htx_pclk, HHI_GCLK_MPEG2, 4);
1956static MESON_GATE(g12a_bt656, HHI_GCLK_MPEG2, 6);
1957static MESON_GATE(g12a_usb1_to_ddr, HHI_GCLK_MPEG2, 8);
1958static MESON_GATE(g12a_mmc_pclk, HHI_GCLK_MPEG2, 11);
1959static MESON_GATE(g12a_uart2, HHI_GCLK_MPEG2, 15);
1960static MESON_GATE(g12a_vpu_intr, HHI_GCLK_MPEG2, 25);
1961static MESON_GATE(g12a_gic, HHI_GCLK_MPEG2, 30);
1962
1963static MESON_GATE(g12a_vclk2_venci0, HHI_GCLK_OTHER, 1);
1964static MESON_GATE(g12a_vclk2_venci1, HHI_GCLK_OTHER, 2);
1965static MESON_GATE(g12a_vclk2_vencp0, HHI_GCLK_OTHER, 3);
1966static MESON_GATE(g12a_vclk2_vencp1, HHI_GCLK_OTHER, 4);
1967static MESON_GATE(g12a_vclk2_venct0, HHI_GCLK_OTHER, 5);
1968static MESON_GATE(g12a_vclk2_venct1, HHI_GCLK_OTHER, 6);
1969static MESON_GATE(g12a_vclk2_other, HHI_GCLK_OTHER, 7);
1970static MESON_GATE(g12a_vclk2_enci, HHI_GCLK_OTHER, 8);
1971static MESON_GATE(g12a_vclk2_encp, HHI_GCLK_OTHER, 9);
1972static MESON_GATE(g12a_dac_clk, HHI_GCLK_OTHER, 10);
1973static MESON_GATE(g12a_aoclk_gate, HHI_GCLK_OTHER, 14);
1974static MESON_GATE(g12a_iec958_gate, HHI_GCLK_OTHER, 16);
1975static MESON_GATE(g12a_enc480p, HHI_GCLK_OTHER, 20);
1976static MESON_GATE(g12a_rng1, HHI_GCLK_OTHER, 21);
1977static MESON_GATE(g12a_vclk2_enct, HHI_GCLK_OTHER, 22);
1978static MESON_GATE(g12a_vclk2_encl, HHI_GCLK_OTHER, 23);
1979static MESON_GATE(g12a_vclk2_venclmmc, HHI_GCLK_OTHER, 24);
1980static MESON_GATE(g12a_vclk2_vencl, HHI_GCLK_OTHER, 25);
1981static MESON_GATE(g12a_vclk2_other1, HHI_GCLK_OTHER, 26);
1982
1983static MESON_GATE_RO(g12a_dma, HHI_GCLK_OTHER2, 0);
1984static MESON_GATE_RO(g12a_efuse, HHI_GCLK_OTHER2, 1);
1985static MESON_GATE_RO(g12a_rom_boot, HHI_GCLK_OTHER2, 2);
1986static MESON_GATE_RO(g12a_reset_sec, HHI_GCLK_OTHER2, 3);
1987static MESON_GATE_RO(g12a_sec_ahb_apb3, HHI_GCLK_OTHER2, 4);
1988
1989/* Array of all clocks provided by this provider */
1990static struct clk_hw_onecell_data g12a_hw_onecell_data = {
1991 .hws = {
1992 [CLKID_SYS_PLL] = &g12a_sys_pll.hw,
1993 [CLKID_FIXED_PLL] = &g12a_fixed_pll.hw,
1994 [CLKID_FCLK_DIV2] = &g12a_fclk_div2.hw,
1995 [CLKID_FCLK_DIV3] = &g12a_fclk_div3.hw,
1996 [CLKID_FCLK_DIV4] = &g12a_fclk_div4.hw,
1997 [CLKID_FCLK_DIV5] = &g12a_fclk_div5.hw,
1998 [CLKID_FCLK_DIV7] = &g12a_fclk_div7.hw,
1999 [CLKID_FCLK_DIV2P5] = &g12a_fclk_div2p5.hw,
2000 [CLKID_GP0_PLL] = &g12a_gp0_pll.hw,
2001 [CLKID_MPEG_SEL] = &g12a_mpeg_clk_sel.hw,
2002 [CLKID_MPEG_DIV] = &g12a_mpeg_clk_div.hw,
2003 [CLKID_CLK81] = &g12a_clk81.hw,
2004 [CLKID_MPLL0] = &g12a_mpll0.hw,
2005 [CLKID_MPLL1] = &g12a_mpll1.hw,
2006 [CLKID_MPLL2] = &g12a_mpll2.hw,
2007 [CLKID_MPLL3] = &g12a_mpll3.hw,
2008 [CLKID_DDR] = &g12a_ddr.hw,
2009 [CLKID_DOS] = &g12a_dos.hw,
2010 [CLKID_AUDIO_LOCKER] = &g12a_audio_locker.hw,
2011 [CLKID_MIPI_DSI_HOST] = &g12a_mipi_dsi_host.hw,
2012 [CLKID_ETH_PHY] = &g12a_eth_phy.hw,
2013 [CLKID_ISA] = &g12a_isa.hw,
2014 [CLKID_PL301] = &g12a_pl301.hw,
2015 [CLKID_PERIPHS] = &g12a_periphs.hw,
2016 [CLKID_SPICC0] = &g12a_spicc_0.hw,
2017 [CLKID_I2C] = &g12a_i2c.hw,
2018 [CLKID_SANA] = &g12a_sana.hw,
2019 [CLKID_SD] = &g12a_sd.hw,
2020 [CLKID_RNG0] = &g12a_rng0.hw,
2021 [CLKID_UART0] = &g12a_uart0.hw,
2022 [CLKID_SPICC1] = &g12a_spicc_1.hw,
2023 [CLKID_HIU_IFACE] = &g12a_hiu_reg.hw,
2024 [CLKID_MIPI_DSI_PHY] = &g12a_mipi_dsi_phy.hw,
2025 [CLKID_ASSIST_MISC] = &g12a_assist_misc.hw,
2026 [CLKID_SD_EMMC_A] = &g12a_emmc_a.hw,
2027 [CLKID_SD_EMMC_B] = &g12a_emmc_b.hw,
2028 [CLKID_SD_EMMC_C] = &g12a_emmc_c.hw,
2029 [CLKID_AUDIO_CODEC] = &g12a_audio_codec.hw,
2030 [CLKID_AUDIO] = &g12a_audio.hw,
2031 [CLKID_ETH] = &g12a_eth_core.hw,
2032 [CLKID_DEMUX] = &g12a_demux.hw,
2033 [CLKID_AUDIO_IFIFO] = &g12a_audio_ififo.hw,
2034 [CLKID_ADC] = &g12a_adc.hw,
2035 [CLKID_UART1] = &g12a_uart1.hw,
2036 [CLKID_G2D] = &g12a_g2d.hw,
2037 [CLKID_RESET] = &g12a_reset.hw,
2038 [CLKID_PCIE_COMB] = &g12a_pcie_comb.hw,
2039 [CLKID_PARSER] = &g12a_parser.hw,
2040 [CLKID_USB] = &g12a_usb_general.hw,
2041 [CLKID_PCIE_PHY] = &g12a_pcie_phy.hw,
2042 [CLKID_AHB_ARB0] = &g12a_ahb_arb0.hw,
2043 [CLKID_AHB_DATA_BUS] = &g12a_ahb_data_bus.hw,
2044 [CLKID_AHB_CTRL_BUS] = &g12a_ahb_ctrl_bus.hw,
2045 [CLKID_HTX_HDCP22] = &g12a_htx_hdcp22.hw,
2046 [CLKID_HTX_PCLK] = &g12a_htx_pclk.hw,
2047 [CLKID_BT656] = &g12a_bt656.hw,
2048 [CLKID_USB1_DDR_BRIDGE] = &g12a_usb1_to_ddr.hw,
2049 [CLKID_MMC_PCLK] = &g12a_mmc_pclk.hw,
2050 [CLKID_UART2] = &g12a_uart2.hw,
2051 [CLKID_VPU_INTR] = &g12a_vpu_intr.hw,
2052 [CLKID_GIC] = &g12a_gic.hw,
2053 [CLKID_SD_EMMC_A_CLK0_SEL] = &g12a_sd_emmc_a_clk0_sel.hw,
2054 [CLKID_SD_EMMC_A_CLK0_DIV] = &g12a_sd_emmc_a_clk0_div.hw,
2055 [CLKID_SD_EMMC_A_CLK0] = &g12a_sd_emmc_a_clk0.hw,
2056 [CLKID_SD_EMMC_B_CLK0_SEL] = &g12a_sd_emmc_b_clk0_sel.hw,
2057 [CLKID_SD_EMMC_B_CLK0_DIV] = &g12a_sd_emmc_b_clk0_div.hw,
2058 [CLKID_SD_EMMC_B_CLK0] = &g12a_sd_emmc_b_clk0.hw,
2059 [CLKID_SD_EMMC_C_CLK0_SEL] = &g12a_sd_emmc_c_clk0_sel.hw,
2060 [CLKID_SD_EMMC_C_CLK0_DIV] = &g12a_sd_emmc_c_clk0_div.hw,
2061 [CLKID_SD_EMMC_C_CLK0] = &g12a_sd_emmc_c_clk0.hw,
2062 [CLKID_MPLL0_DIV] = &g12a_mpll0_div.hw,
2063 [CLKID_MPLL1_DIV] = &g12a_mpll1_div.hw,
2064 [CLKID_MPLL2_DIV] = &g12a_mpll2_div.hw,
2065 [CLKID_MPLL3_DIV] = &g12a_mpll3_div.hw,
2066 [CLKID_FCLK_DIV2_DIV] = &g12a_fclk_div2_div.hw,
2067 [CLKID_FCLK_DIV3_DIV] = &g12a_fclk_div3_div.hw,
2068 [CLKID_FCLK_DIV4_DIV] = &g12a_fclk_div4_div.hw,
2069 [CLKID_FCLK_DIV5_DIV] = &g12a_fclk_div5_div.hw,
2070 [CLKID_FCLK_DIV7_DIV] = &g12a_fclk_div7_div.hw,
2071 [CLKID_FCLK_DIV2P5_DIV] = &g12a_fclk_div2p5_div.hw,
2072 [CLKID_HIFI_PLL] = &g12a_hifi_pll.hw,
2073 [CLKID_VCLK2_VENCI0] = &g12a_vclk2_venci0.hw,
2074 [CLKID_VCLK2_VENCI1] = &g12a_vclk2_venci1.hw,
2075 [CLKID_VCLK2_VENCP0] = &g12a_vclk2_vencp0.hw,
2076 [CLKID_VCLK2_VENCP1] = &g12a_vclk2_vencp1.hw,
2077 [CLKID_VCLK2_VENCT0] = &g12a_vclk2_venct0.hw,
2078 [CLKID_VCLK2_VENCT1] = &g12a_vclk2_venct1.hw,
2079 [CLKID_VCLK2_OTHER] = &g12a_vclk2_other.hw,
2080 [CLKID_VCLK2_ENCI] = &g12a_vclk2_enci.hw,
2081 [CLKID_VCLK2_ENCP] = &g12a_vclk2_encp.hw,
2082 [CLKID_DAC_CLK] = &g12a_dac_clk.hw,
2083 [CLKID_AOCLK] = &g12a_aoclk_gate.hw,
2084 [CLKID_IEC958] = &g12a_iec958_gate.hw,
2085 [CLKID_ENC480P] = &g12a_enc480p.hw,
2086 [CLKID_RNG1] = &g12a_rng1.hw,
2087 [CLKID_VCLK2_ENCT] = &g12a_vclk2_enct.hw,
2088 [CLKID_VCLK2_ENCL] = &g12a_vclk2_encl.hw,
2089 [CLKID_VCLK2_VENCLMMC] = &g12a_vclk2_venclmmc.hw,
2090 [CLKID_VCLK2_VENCL] = &g12a_vclk2_vencl.hw,
2091 [CLKID_VCLK2_OTHER1] = &g12a_vclk2_other1.hw,
2092 [CLKID_FIXED_PLL_DCO] = &g12a_fixed_pll_dco.hw,
2093 [CLKID_SYS_PLL_DCO] = &g12a_sys_pll_dco.hw,
2094 [CLKID_GP0_PLL_DCO] = &g12a_gp0_pll_dco.hw,
2095 [CLKID_HIFI_PLL_DCO] = &g12a_hifi_pll_dco.hw,
2096 [CLKID_DMA] = &g12a_dma.hw,
2097 [CLKID_EFUSE] = &g12a_efuse.hw,
2098 [CLKID_ROM_BOOT] = &g12a_rom_boot.hw,
2099 [CLKID_RESET_SEC] = &g12a_reset_sec.hw,
2100 [CLKID_SEC_AHB_APB3] = &g12a_sec_ahb_apb3.hw,
2101 [CLKID_MPLL_PREDIV] = &g12a_mpll_prediv.hw,
2102 [CLKID_VPU_0_SEL] = &g12a_vpu_0_sel.hw,
2103 [CLKID_VPU_0_DIV] = &g12a_vpu_0_div.hw,
2104 [CLKID_VPU_0] = &g12a_vpu_0.hw,
2105 [CLKID_VPU_1_SEL] = &g12a_vpu_1_sel.hw,
2106 [CLKID_VPU_1_DIV] = &g12a_vpu_1_div.hw,
2107 [CLKID_VPU_1] = &g12a_vpu_1.hw,
2108 [CLKID_VPU] = &g12a_vpu.hw,
2109 [CLKID_VAPB_0_SEL] = &g12a_vapb_0_sel.hw,
2110 [CLKID_VAPB_0_DIV] = &g12a_vapb_0_div.hw,
2111 [CLKID_VAPB_0] = &g12a_vapb_0.hw,
2112 [CLKID_VAPB_1_SEL] = &g12a_vapb_1_sel.hw,
2113 [CLKID_VAPB_1_DIV] = &g12a_vapb_1_div.hw,
2114 [CLKID_VAPB_1] = &g12a_vapb_1.hw,
2115 [CLKID_VAPB_SEL] = &g12a_vapb_sel.hw,
2116 [CLKID_VAPB] = &g12a_vapb.hw,
2117 [CLKID_HDMI_PLL_DCO] = &g12a_hdmi_pll_dco.hw,
2118 [CLKID_HDMI_PLL_OD] = &g12a_hdmi_pll_od.hw,
2119 [CLKID_HDMI_PLL_OD2] = &g12a_hdmi_pll_od2.hw,
2120 [CLKID_HDMI_PLL] = &g12a_hdmi_pll.hw,
2121 [CLKID_VID_PLL] = &g12a_vid_pll_div.hw,
2122 [CLKID_VID_PLL_SEL] = &g12a_vid_pll_sel.hw,
2123 [CLKID_VID_PLL_DIV] = &g12a_vid_pll.hw,
2124 [CLKID_VCLK_SEL] = &g12a_vclk_sel.hw,
2125 [CLKID_VCLK2_SEL] = &g12a_vclk2_sel.hw,
2126 [CLKID_VCLK_INPUT] = &g12a_vclk_input.hw,
2127 [CLKID_VCLK2_INPUT] = &g12a_vclk2_input.hw,
2128 [CLKID_VCLK_DIV] = &g12a_vclk_div.hw,
2129 [CLKID_VCLK2_DIV] = &g12a_vclk2_div.hw,
2130 [CLKID_VCLK] = &g12a_vclk.hw,
2131 [CLKID_VCLK2] = &g12a_vclk2.hw,
2132 [CLKID_VCLK_DIV1] = &g12a_vclk_div1.hw,
2133 [CLKID_VCLK_DIV2_EN] = &g12a_vclk_div2_en.hw,
2134 [CLKID_VCLK_DIV4_EN] = &g12a_vclk_div4_en.hw,
2135 [CLKID_VCLK_DIV6_EN] = &g12a_vclk_div6_en.hw,
2136 [CLKID_VCLK_DIV12_EN] = &g12a_vclk_div12_en.hw,
2137 [CLKID_VCLK2_DIV1] = &g12a_vclk2_div1.hw,
2138 [CLKID_VCLK2_DIV2_EN] = &g12a_vclk2_div2_en.hw,
2139 [CLKID_VCLK2_DIV4_EN] = &g12a_vclk2_div4_en.hw,
2140 [CLKID_VCLK2_DIV6_EN] = &g12a_vclk2_div6_en.hw,
2141 [CLKID_VCLK2_DIV12_EN] = &g12a_vclk2_div12_en.hw,
2142 [CLKID_VCLK_DIV2] = &g12a_vclk_div2.hw,
2143 [CLKID_VCLK_DIV4] = &g12a_vclk_div4.hw,
2144 [CLKID_VCLK_DIV6] = &g12a_vclk_div6.hw,
2145 [CLKID_VCLK_DIV12] = &g12a_vclk_div12.hw,
2146 [CLKID_VCLK2_DIV2] = &g12a_vclk2_div2.hw,
2147 [CLKID_VCLK2_DIV4] = &g12a_vclk2_div4.hw,
2148 [CLKID_VCLK2_DIV6] = &g12a_vclk2_div6.hw,
2149 [CLKID_VCLK2_DIV12] = &g12a_vclk2_div12.hw,
2150 [CLKID_CTS_ENCI_SEL] = &g12a_cts_enci_sel.hw,
2151 [CLKID_CTS_ENCP_SEL] = &g12a_cts_encp_sel.hw,
2152 [CLKID_CTS_VDAC_SEL] = &g12a_cts_vdac_sel.hw,
2153 [CLKID_HDMI_TX_SEL] = &g12a_hdmi_tx_sel.hw,
2154 [CLKID_CTS_ENCI] = &g12a_cts_enci.hw,
2155 [CLKID_CTS_ENCP] = &g12a_cts_encp.hw,
2156 [CLKID_CTS_VDAC] = &g12a_cts_vdac.hw,
2157 [CLKID_HDMI_TX] = &g12a_hdmi_tx.hw,
2158 [CLKID_HDMI_SEL] = &g12a_hdmi_sel.hw,
2159 [CLKID_HDMI_DIV] = &g12a_hdmi_div.hw,
2160 [CLKID_HDMI] = &g12a_hdmi.hw,
2161 [CLKID_MALI_0_SEL] = &g12a_mali_0_sel.hw,
2162 [CLKID_MALI_0_DIV] = &g12a_mali_0_div.hw,
2163 [CLKID_MALI_0] = &g12a_mali_0.hw,
2164 [CLKID_MALI_1_SEL] = &g12a_mali_1_sel.hw,
2165 [CLKID_MALI_1_DIV] = &g12a_mali_1_div.hw,
2166 [CLKID_MALI_1] = &g12a_mali_1.hw,
2167 [CLKID_MALI] = &g12a_mali.hw,
2168 [CLKID_MPLL_5OM_DIV] = &g12a_mpll_50m_div.hw,
2169 [CLKID_MPLL_5OM] = &g12a_mpll_50m.hw,
2170 [NR_CLKS] = NULL,
2171 },
2172 .num = NR_CLKS,
2173};
2174
2175/* Convenience table to populate regmap in .probe */
2176static struct clk_regmap *const g12a_clk_regmaps[] = {
2177 &g12a_clk81,
2178 &g12a_dos,
2179 &g12a_ddr,
2180 &g12a_audio_locker,
2181 &g12a_mipi_dsi_host,
2182 &g12a_eth_phy,
2183 &g12a_isa,
2184 &g12a_pl301,
2185 &g12a_periphs,
2186 &g12a_spicc_0,
2187 &g12a_i2c,
2188 &g12a_sana,
2189 &g12a_sd,
2190 &g12a_rng0,
2191 &g12a_uart0,
2192 &g12a_spicc_1,
2193 &g12a_hiu_reg,
2194 &g12a_mipi_dsi_phy,
2195 &g12a_assist_misc,
2196 &g12a_emmc_a,
2197 &g12a_emmc_b,
2198 &g12a_emmc_c,
2199 &g12a_audio_codec,
2200 &g12a_audio,
2201 &g12a_eth_core,
2202 &g12a_demux,
2203 &g12a_audio_ififo,
2204 &g12a_adc,
2205 &g12a_uart1,
2206 &g12a_g2d,
2207 &g12a_reset,
2208 &g12a_pcie_comb,
2209 &g12a_parser,
2210 &g12a_usb_general,
2211 &g12a_pcie_phy,
2212 &g12a_ahb_arb0,
2213 &g12a_ahb_data_bus,
2214 &g12a_ahb_ctrl_bus,
2215 &g12a_htx_hdcp22,
2216 &g12a_htx_pclk,
2217 &g12a_bt656,
2218 &g12a_usb1_to_ddr,
2219 &g12a_mmc_pclk,
2220 &g12a_vpu_intr,
2221 &g12a_gic,
2222 &g12a_sd_emmc_a_clk0,
2223 &g12a_sd_emmc_b_clk0,
2224 &g12a_sd_emmc_c_clk0,
2225 &g12a_mpeg_clk_div,
2226 &g12a_sd_emmc_a_clk0_div,
2227 &g12a_sd_emmc_b_clk0_div,
2228 &g12a_sd_emmc_c_clk0_div,
2229 &g12a_mpeg_clk_sel,
2230 &g12a_sd_emmc_a_clk0_sel,
2231 &g12a_sd_emmc_b_clk0_sel,
2232 &g12a_sd_emmc_c_clk0_sel,
2233 &g12a_mpll0,
2234 &g12a_mpll1,
2235 &g12a_mpll2,
2236 &g12a_mpll3,
2237 &g12a_mpll0_div,
2238 &g12a_mpll1_div,
2239 &g12a_mpll2_div,
2240 &g12a_mpll3_div,
2241 &g12a_fixed_pll,
2242 &g12a_sys_pll,
2243 &g12a_gp0_pll,
2244 &g12a_hifi_pll,
2245 &g12a_vclk2_venci0,
2246 &g12a_vclk2_venci1,
2247 &g12a_vclk2_vencp0,
2248 &g12a_vclk2_vencp1,
2249 &g12a_vclk2_venct0,
2250 &g12a_vclk2_venct1,
2251 &g12a_vclk2_other,
2252 &g12a_vclk2_enci,
2253 &g12a_vclk2_encp,
2254 &g12a_dac_clk,
2255 &g12a_aoclk_gate,
2256 &g12a_iec958_gate,
2257 &g12a_enc480p,
2258 &g12a_rng1,
2259 &g12a_vclk2_enct,
2260 &g12a_vclk2_encl,
2261 &g12a_vclk2_venclmmc,
2262 &g12a_vclk2_vencl,
2263 &g12a_vclk2_other1,
2264 &g12a_fixed_pll_dco,
2265 &g12a_sys_pll_dco,
2266 &g12a_gp0_pll_dco,
2267 &g12a_hifi_pll_dco,
2268 &g12a_fclk_div2,
2269 &g12a_fclk_div3,
2270 &g12a_fclk_div4,
2271 &g12a_fclk_div5,
2272 &g12a_fclk_div7,
2273 &g12a_fclk_div2p5,
2274 &g12a_dma,
2275 &g12a_efuse,
2276 &g12a_rom_boot,
2277 &g12a_reset_sec,
2278 &g12a_sec_ahb_apb3,
2279 &g12a_vpu_0_sel,
2280 &g12a_vpu_0_div,
2281 &g12a_vpu_0,
2282 &g12a_vpu_1_sel,
2283 &g12a_vpu_1_div,
2284 &g12a_vpu_1,
2285 &g12a_vpu,
2286 &g12a_vapb_0_sel,
2287 &g12a_vapb_0_div,
2288 &g12a_vapb_0,
2289 &g12a_vapb_1_sel,
2290 &g12a_vapb_1_div,
2291 &g12a_vapb_1,
2292 &g12a_vapb_sel,
2293 &g12a_vapb,
2294 &g12a_hdmi_pll_dco,
2295 &g12a_hdmi_pll_od,
2296 &g12a_hdmi_pll_od2,
2297 &g12a_hdmi_pll,
2298 &g12a_vid_pll_div,
2299 &g12a_vid_pll_sel,
2300 &g12a_vid_pll,
2301 &g12a_vclk_sel,
2302 &g12a_vclk2_sel,
2303 &g12a_vclk_input,
2304 &g12a_vclk2_input,
2305 &g12a_vclk_div,
2306 &g12a_vclk2_div,
2307 &g12a_vclk,
2308 &g12a_vclk2,
2309 &g12a_vclk_div1,
2310 &g12a_vclk_div2_en,
2311 &g12a_vclk_div4_en,
2312 &g12a_vclk_div6_en,
2313 &g12a_vclk_div12_en,
2314 &g12a_vclk2_div1,
2315 &g12a_vclk2_div2_en,
2316 &g12a_vclk2_div4_en,
2317 &g12a_vclk2_div6_en,
2318 &g12a_vclk2_div12_en,
2319 &g12a_cts_enci_sel,
2320 &g12a_cts_encp_sel,
2321 &g12a_cts_vdac_sel,
2322 &g12a_hdmi_tx_sel,
2323 &g12a_cts_enci,
2324 &g12a_cts_encp,
2325 &g12a_cts_vdac,
2326 &g12a_hdmi_tx,
2327 &g12a_hdmi_sel,
2328 &g12a_hdmi_div,
2329 &g12a_hdmi,
2330 &g12a_mali_0_sel,
2331 &g12a_mali_0_div,
2332 &g12a_mali_0,
2333 &g12a_mali_1_sel,
2334 &g12a_mali_1_div,
2335 &g12a_mali_1,
2336 &g12a_mali,
2337 &g12a_mpll_50m,
2338};
2339
2340static const struct meson_eeclkc_data g12a_clkc_data = {
2341 .regmap_clks = g12a_clk_regmaps,
2342 .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
2343 .hw_onecell_data = &g12a_hw_onecell_data
2344};
2345
2346static const struct of_device_id clkc_match_table[] = {
2347 { .compatible = "amlogic,g12a-clkc", .data = &g12a_clkc_data },
2348 {}
2349};
2350
2351static struct platform_driver g12a_driver = {
2352 .probe = meson_eeclkc_probe,
2353 .driver = {
2354 .name = "g12a-clkc",
2355 .of_match_table = clkc_match_table,
2356 },
2357};
2358
2359builtin_platform_driver(g12a_driver);
diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h
new file mode 100644
index 000000000000..f399dfe1401c
--- /dev/null
+++ b/drivers/clk/meson/g12a.h
@@ -0,0 +1,175 @@
1/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
2/*
3 * Copyright (c) 2016 Amlogic, Inc.
4 * Author: Michael Turquette <mturquette@baylibre.com>
5 *
6 * Copyright (c) 2018 Amlogic, inc.
7 * Author: Qiufang Dai <qiufang.dai@amlogic.com>
8 * Author: Jian Hu <jian.hu@amlogic.com>
9 *
10 */
11#ifndef __G12A_H
12#define __G12A_H
13
14/*
15 * Clock controller register offsets
16 *
17 * Register offsets from the data sheet must be multiplied by 4 before
18 * adding them to the base address to get the right value.
19 */
20#define HHI_MIPI_CNTL0 0x000
21#define HHI_MIPI_CNTL1 0x004
22#define HHI_MIPI_CNTL2 0x008
23#define HHI_MIPI_STS 0x00C
24#define HHI_GP0_PLL_CNTL0 0x040
25#define HHI_GP0_PLL_CNTL1 0x044
26#define HHI_GP0_PLL_CNTL2 0x048
27#define HHI_GP0_PLL_CNTL3 0x04C
28#define HHI_GP0_PLL_CNTL4 0x050
29#define HHI_GP0_PLL_CNTL5 0x054
30#define HHI_GP0_PLL_CNTL6 0x058
31#define HHI_GP0_PLL_STS 0x05C
32#define HHI_PCIE_PLL_CNTL0 0x098
33#define HHI_PCIE_PLL_CNTL1 0x09C
34#define HHI_PCIE_PLL_CNTL2 0x0A0
35#define HHI_PCIE_PLL_CNTL3 0x0A4
36#define HHI_PCIE_PLL_CNTL4 0x0A8
37#define HHI_PCIE_PLL_CNTL5 0x0AC
38#define HHI_PCIE_PLL_STS 0x0B8
39#define HHI_HIFI_PLL_CNTL0 0x0D8
40#define HHI_HIFI_PLL_CNTL1 0x0DC
41#define HHI_HIFI_PLL_CNTL2 0x0E0
42#define HHI_HIFI_PLL_CNTL3 0x0E4
43#define HHI_HIFI_PLL_CNTL4 0x0E8
44#define HHI_HIFI_PLL_CNTL5 0x0EC
45#define HHI_HIFI_PLL_CNTL6 0x0F0
46#define HHI_VIID_CLK_DIV 0x128
47#define HHI_VIID_CLK_CNTL 0x12C
48#define HHI_GCLK_MPEG0 0x140
49#define HHI_GCLK_MPEG1 0x144
50#define HHI_GCLK_MPEG2 0x148
51#define HHI_GCLK_OTHER 0x150
52#define HHI_GCLK_OTHER2 0x154
53#define HHI_VID_CLK_DIV 0x164
54#define HHI_MPEG_CLK_CNTL 0x174
55#define HHI_AUD_CLK_CNTL 0x178
56#define HHI_VID_CLK_CNTL 0x17c
57#define HHI_TS_CLK_CNTL 0x190
58#define HHI_VID_CLK_CNTL2 0x194
59#define HHI_SYS_CPU_CLK_CNTL0 0x19c
60#define HHI_VID_PLL_CLK_DIV 0x1A0
61#define HHI_MALI_CLK_CNTL 0x1b0
62#define HHI_VPU_CLKC_CNTL 0x1b4
63#define HHI_VPU_CLK_CNTL 0x1bC
64#define HHI_HDMI_CLK_CNTL 0x1CC
65#define HHI_VDEC_CLK_CNTL 0x1E0
66#define HHI_VDEC2_CLK_CNTL 0x1E4
67#define HHI_VDEC3_CLK_CNTL 0x1E8
68#define HHI_VDEC4_CLK_CNTL 0x1EC
69#define HHI_HDCP22_CLK_CNTL 0x1F0
70#define HHI_VAPBCLK_CNTL 0x1F4
71#define HHI_VPU_CLKB_CNTL 0x20C
72#define HHI_GEN_CLK_CNTL 0x228
73#define HHI_VDIN_MEAS_CLK_CNTL 0x250
74#define HHI_MIPIDSI_PHY_CLK_CNTL 0x254
75#define HHI_NAND_CLK_CNTL 0x25C
76#define HHI_SD_EMMC_CLK_CNTL 0x264
77#define HHI_MPLL_CNTL0 0x278
78#define HHI_MPLL_CNTL1 0x27C
79#define HHI_MPLL_CNTL2 0x280
80#define HHI_MPLL_CNTL3 0x284
81#define HHI_MPLL_CNTL4 0x288
82#define HHI_MPLL_CNTL5 0x28c
83#define HHI_MPLL_CNTL6 0x290
84#define HHI_MPLL_CNTL7 0x294
85#define HHI_MPLL_CNTL8 0x298
86#define HHI_FIX_PLL_CNTL0 0x2A0
87#define HHI_FIX_PLL_CNTL1 0x2A4
88#define HHI_FIX_PLL_CNTL3 0x2AC
89#define HHI_SYS_PLL_CNTL0 0x2f4
90#define HHI_SYS_PLL_CNTL1 0x2f8
91#define HHI_SYS_PLL_CNTL2 0x2fc
92#define HHI_SYS_PLL_CNTL3 0x300
93#define HHI_SYS_PLL_CNTL4 0x304
94#define HHI_SYS_PLL_CNTL5 0x308
95#define HHI_SYS_PLL_CNTL6 0x30c
96#define HHI_HDMI_PLL_CNTL0 0x320
97#define HHI_HDMI_PLL_CNTL1 0x324
98#define HHI_HDMI_PLL_CNTL2 0x328
99#define HHI_HDMI_PLL_CNTL3 0x32c
100#define HHI_HDMI_PLL_CNTL4 0x330
101#define HHI_HDMI_PLL_CNTL5 0x334
102#define HHI_HDMI_PLL_CNTL6 0x338
103#define HHI_SPICC_CLK_CNTL 0x3dc
104
105/*
106 * CLKID index values
107 *
108 * These indices are entirely contrived and do not map onto the hardware.
109 * It has now been decided to expose everything by default in the DT header:
110 * include/dt-bindings/clock/g12a-clkc.h. Only the clocks ids we don't want
111 * to expose, such as the internal muxes and dividers of composite clocks,
112 * will remain defined here.
113 */
114#define CLKID_MPEG_SEL 8
115#define CLKID_MPEG_DIV 9
116#define CLKID_SD_EMMC_A_CLK0_SEL 63
117#define CLKID_SD_EMMC_A_CLK0_DIV 64
118#define CLKID_SD_EMMC_B_CLK0_SEL 65
119#define CLKID_SD_EMMC_B_CLK0_DIV 66
120#define CLKID_SD_EMMC_C_CLK0_SEL 67
121#define CLKID_SD_EMMC_C_CLK0_DIV 68
122#define CLKID_MPLL0_DIV 69
123#define CLKID_MPLL1_DIV 70
124#define CLKID_MPLL2_DIV 71
125#define CLKID_MPLL3_DIV 72
126#define CLKID_MPLL_PREDIV 73
127#define CLKID_FCLK_DIV2_DIV 75
128#define CLKID_FCLK_DIV3_DIV 76
129#define CLKID_FCLK_DIV4_DIV 77
130#define CLKID_FCLK_DIV5_DIV 78
131#define CLKID_FCLK_DIV7_DIV 79
132#define CLKID_FCLK_DIV2P5_DIV 100
133#define CLKID_FIXED_PLL_DCO 101
134#define CLKID_SYS_PLL_DCO 102
135#define CLKID_GP0_PLL_DCO 103
136#define CLKID_HIFI_PLL_DCO 104
137#define CLKID_VPU_0_DIV 111
138#define CLKID_VPU_1_DIV 114
139#define CLKID_VAPB_0_DIV 118
140#define CLKID_VAPB_1_DIV 121
141#define CLKID_HDMI_PLL_DCO 125
142#define CLKID_HDMI_PLL_OD 126
143#define CLKID_HDMI_PLL_OD2 127
144#define CLKID_VID_PLL_SEL 130
145#define CLKID_VID_PLL_DIV 131
146#define CLKID_VCLK_SEL 132
147#define CLKID_VCLK2_SEL 133
148#define CLKID_VCLK_INPUT 134
149#define CLKID_VCLK2_INPUT 135
150#define CLKID_VCLK_DIV 136
151#define CLKID_VCLK2_DIV 137
152#define CLKID_VCLK_DIV2_EN 140
153#define CLKID_VCLK_DIV4_EN 141
154#define CLKID_VCLK_DIV6_EN 142
155#define CLKID_VCLK_DIV12_EN 143
156#define CLKID_VCLK2_DIV2_EN 144
157#define CLKID_VCLK2_DIV4_EN 145
158#define CLKID_VCLK2_DIV6_EN 146
159#define CLKID_VCLK2_DIV12_EN 147
160#define CLKID_CTS_ENCI_SEL 158
161#define CLKID_CTS_ENCP_SEL 159
162#define CLKID_CTS_VDAC_SEL 160
163#define CLKID_HDMI_TX_SEL 161
164#define CLKID_HDMI_SEL 166
165#define CLKID_HDMI_DIV 167
166#define CLKID_MALI_0_DIV 170
167#define CLKID_MALI_1_DIV 173
168#define CLKID_MPLL_5OM_DIV 176
169
170#define NR_CLKS 178
171
172/* include the CLKIDs that have been made part of the DT binding */
173#include <dt-bindings/clock/g12a-clkc.h>
174
175#endif /* __G12A_H */
diff --git a/drivers/clk/meson/gxbb-aoclk-32k.c b/drivers/clk/meson/gxbb-aoclk-32k.c
deleted file mode 100644
index 680467141a1d..000000000000
--- a/drivers/clk/meson/gxbb-aoclk-32k.c
+++ /dev/null
@@ -1,193 +0,0 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2017 BayLibre, SAS.
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 */
6
7#include <linux/clk-provider.h>
8#include <linux/bitfield.h>
9#include <linux/regmap.h>
10#include "gxbb-aoclk.h"
11
12/*
13 * The AO Domain embeds a dual/divider to generate a more precise
14 * 32,768KHz clock for low-power suspend mode and CEC.
15 * ______ ______
16 * | | | |
17 * ______ | Div1 |-| Cnt1 | ______
18 * | | /|______| |______|\ | |
19 * Xtal-->| Gate |---| ______ ______ X-X--| Gate |-->
20 * |______| | \| | | |/ | |______|
21 * | | Div2 |-| Cnt2 | |
22 * | |______| |______| |
23 * |_______________________|
24 *
25 * The dividing can be switched to single or dual, with a counter
26 * for each divider to set when the switching is done.
27 * The entire dividing mechanism can be also bypassed.
28 */
29
30#define CLK_CNTL0_N1_MASK GENMASK(11, 0)
31#define CLK_CNTL0_N2_MASK GENMASK(23, 12)
32#define CLK_CNTL0_DUALDIV_EN BIT(28)
33#define CLK_CNTL0_OUT_GATE_EN BIT(30)
34#define CLK_CNTL0_IN_GATE_EN BIT(31)
35
36#define CLK_CNTL1_M1_MASK GENMASK(11, 0)
37#define CLK_CNTL1_M2_MASK GENMASK(23, 12)
38#define CLK_CNTL1_BYPASS_EN BIT(24)
39#define CLK_CNTL1_SELECT_OSC BIT(27)
40
41#define PWR_CNTL_ALT_32K_SEL GENMASK(13, 10)
42
43struct cec_32k_freq_table {
44 unsigned long parent_rate;
45 unsigned long target_rate;
46 bool dualdiv;
47 unsigned int n1;
48 unsigned int n2;
49 unsigned int m1;
50 unsigned int m2;
51};
52
53static const struct cec_32k_freq_table aoclk_cec_32k_table[] = {
54 [0] = {
55 .parent_rate = 24000000,
56 .target_rate = 32768,
57 .dualdiv = true,
58 .n1 = 733,
59 .n2 = 732,
60 .m1 = 8,
61 .m2 = 11,
62 },
63};
64
65/*
66 * If CLK_CNTL0_DUALDIV_EN == 0
67 * - will use N1 divider only
68 * If CLK_CNTL0_DUALDIV_EN == 1
69 * - hold M1 cycles of N1 divider then changes to N2
70 * - hold M2 cycles of N2 divider then changes to N1
71 * Then we can get more accurate division.
72 */
73static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw,
74 unsigned long parent_rate)
75{
76 struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
77 unsigned long n1;
78 u32 reg0, reg1;
79
80 regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, &reg0);
81 regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, &reg1);
82
83 if (reg1 & CLK_CNTL1_BYPASS_EN)
84 return parent_rate;
85
86 if (reg0 & CLK_CNTL0_DUALDIV_EN) {
87 unsigned long n2, m1, m2, f1, f2, p1, p2;
88
89 n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
90 n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1;
91
92 m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1;
93 m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1;
94
95 f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
96 f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
97
98 p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
99 p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
100
101 return DIV_ROUND_UP(100000000, p1 + p2);
102 }
103
104 n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
105
106 return DIV_ROUND_CLOSEST(parent_rate, n1);
107}
108
109static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate,
110 unsigned long prate)
111{
112 int i;
113
114 for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i)
115 if (aoclk_cec_32k_table[i].parent_rate == prate &&
116 aoclk_cec_32k_table[i].target_rate == rate)
117 return &aoclk_cec_32k_table[i];
118
119 return NULL;
120}
121
122static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate,
123 unsigned long *prate)
124{
125 const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
126 *prate);
127
128 /* If invalid return first one */
129 if (!freq)
130 return aoclk_cec_32k_table[0].target_rate;
131
132 return freq->target_rate;
133}
134
135/*
136 * From the Amlogic init procedure, the IN and OUT gates needs to be handled
137 * in the init procedure to avoid any glitches.
138 */
139
140static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate,
141 unsigned long parent_rate)
142{
143 const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
144 parent_rate);
145 struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
146 u32 reg = 0;
147
148 if (!freq)
149 return -EINVAL;
150
151 /* Disable clock */
152 regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
153 CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN, 0);
154
155 reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1);
156 if (freq->dualdiv)
157 reg |= CLK_CNTL0_DUALDIV_EN |
158 FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1);
159
160 regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, reg);
161
162 reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1);
163 if (freq->dualdiv)
164 reg |= FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1);
165
166 regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, reg);
167
168 /* Enable clock */
169 regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
170 CLK_CNTL0_IN_GATE_EN, CLK_CNTL0_IN_GATE_EN);
171
172 udelay(200);
173
174 regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
175 CLK_CNTL0_OUT_GATE_EN, CLK_CNTL0_OUT_GATE_EN);
176
177 regmap_update_bits(cec_32k->regmap, AO_CRT_CLK_CNTL1,
178 CLK_CNTL1_SELECT_OSC, CLK_CNTL1_SELECT_OSC);
179
180 /* Select 32k from XTAL */
181 regmap_update_bits(cec_32k->regmap,
182 AO_RTI_PWR_CNTL_REG0,
183 PWR_CNTL_ALT_32K_SEL,
184 FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4));
185
186 return 0;
187}
188
189const struct clk_ops meson_aoclk_cec_32k_ops = {
190 .recalc_rate = aoclk_cec_32k_recalc_rate,
191 .round_rate = aoclk_cec_32k_round_rate,
192 .set_rate = aoclk_cec_32k_set_rate,
193};
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 42ed61d3c3fb..449f6ac189d8 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -5,10 +5,23 @@
5 */ 5 */
6#include <linux/platform_device.h> 6#include <linux/platform_device.h>
7#include <linux/mfd/syscon.h> 7#include <linux/mfd/syscon.h>
8#include "clk-regmap.h"
9#include "meson-aoclk.h" 8#include "meson-aoclk.h"
10#include "gxbb-aoclk.h" 9#include "gxbb-aoclk.h"
11 10
11#include "clk-regmap.h"
12#include "clk-dualdiv.h"
13
14#define IN_PREFIX "ao-in-"
15
16/* AO Configuration Clock registers offsets */
17#define AO_RTI_PWR_CNTL_REG1 0x0c
18#define AO_RTI_PWR_CNTL_REG0 0x10
19#define AO_RTI_GEN_CNTL_REG0 0x40
20#define AO_OSCIN_CNTL 0x58
21#define AO_CRT_CLK_CNTL1 0x68
22#define AO_RTC_ALT_CLK_CNTL0 0x94
23#define AO_RTC_ALT_CLK_CNTL1 0x98
24
12#define GXBB_AO_GATE(_name, _bit) \ 25#define GXBB_AO_GATE(_name, _bit) \
13static struct clk_regmap _name##_ao = { \ 26static struct clk_regmap _name##_ao = { \
14 .data = &(struct clk_regmap_gate_data) { \ 27 .data = &(struct clk_regmap_gate_data) { \
@@ -18,7 +31,7 @@ static struct clk_regmap _name##_ao = { \
18 .hw.init = &(struct clk_init_data) { \ 31 .hw.init = &(struct clk_init_data) { \
19 .name = #_name "_ao", \ 32 .name = #_name "_ao", \
20 .ops = &clk_regmap_gate_ops, \ 33 .ops = &clk_regmap_gate_ops, \
21 .parent_names = (const char *[]){ "clk81" }, \ 34 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
22 .num_parents = 1, \ 35 .num_parents = 1, \
23 .flags = CLK_IGNORE_UNUSED, \ 36 .flags = CLK_IGNORE_UNUSED, \
24 }, \ 37 }, \
@@ -31,13 +44,174 @@ GXBB_AO_GATE(uart1, 3);
31GXBB_AO_GATE(uart2, 5); 44GXBB_AO_GATE(uart2, 5);
32GXBB_AO_GATE(ir_blaster, 6); 45GXBB_AO_GATE(ir_blaster, 6);
33 46
34static struct aoclk_cec_32k cec_32k_ao = { 47static struct clk_regmap ao_cts_oscin = {
35 .hw.init = &(struct clk_init_data) { 48 .data = &(struct clk_regmap_gate_data){
36 .name = "cec_32k_ao", 49 .offset = AO_RTI_PWR_CNTL_REG0,
37 .ops = &meson_aoclk_cec_32k_ops, 50 .bit_idx = 6,
38 .parent_names = (const char *[]){ "xtal" }, 51 },
52 .hw.init = &(struct clk_init_data){
53 .name = "ao_cts_oscin",
54 .ops = &clk_regmap_gate_ro_ops,
55 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
56 .num_parents = 1,
57 },
58};
59
60static struct clk_regmap ao_32k_pre = {
61 .data = &(struct clk_regmap_gate_data){
62 .offset = AO_RTC_ALT_CLK_CNTL0,
63 .bit_idx = 31,
64 },
65 .hw.init = &(struct clk_init_data){
66 .name = "ao_32k_pre",
67 .ops = &clk_regmap_gate_ops,
68 .parent_names = (const char *[]){ "ao_cts_oscin" },
69 .num_parents = 1,
70 },
71};
72
73static const struct meson_clk_dualdiv_param gxbb_32k_div_table[] = {
74 {
75 .dual = 1,
76 .n1 = 733,
77 .m1 = 8,
78 .n2 = 732,
79 .m2 = 11,
80 }, {}
81};
82
83static struct clk_regmap ao_32k_div = {
84 .data = &(struct meson_clk_dualdiv_data){
85 .n1 = {
86 .reg_off = AO_RTC_ALT_CLK_CNTL0,
87 .shift = 0,
88 .width = 12,
89 },
90 .n2 = {
91 .reg_off = AO_RTC_ALT_CLK_CNTL0,
92 .shift = 12,
93 .width = 12,
94 },
95 .m1 = {
96 .reg_off = AO_RTC_ALT_CLK_CNTL1,
97 .shift = 0,
98 .width = 12,
99 },
100 .m2 = {
101 .reg_off = AO_RTC_ALT_CLK_CNTL1,
102 .shift = 12,
103 .width = 12,
104 },
105 .dual = {
106 .reg_off = AO_RTC_ALT_CLK_CNTL0,
107 .shift = 28,
108 .width = 1,
109 },
110 .table = gxbb_32k_div_table,
111 },
112 .hw.init = &(struct clk_init_data){
113 .name = "ao_32k_div",
114 .ops = &meson_clk_dualdiv_ops,
115 .parent_names = (const char *[]){ "ao_32k_pre" },
116 .num_parents = 1,
117 },
118};
119
120static struct clk_regmap ao_32k_sel = {
121 .data = &(struct clk_regmap_mux_data) {
122 .offset = AO_RTC_ALT_CLK_CNTL1,
123 .mask = 0x1,
124 .shift = 24,
125 .flags = CLK_MUX_ROUND_CLOSEST,
126 },
127 .hw.init = &(struct clk_init_data){
128 .name = "ao_32k_sel",
129 .ops = &clk_regmap_mux_ops,
130 .parent_names = (const char *[]){ "ao_32k_div",
131 "ao_32k_pre" },
132 .num_parents = 2,
133 .flags = CLK_SET_RATE_PARENT,
134 },
135};
136
137static struct clk_regmap ao_32k = {
138 .data = &(struct clk_regmap_gate_data){
139 .offset = AO_RTC_ALT_CLK_CNTL0,
140 .bit_idx = 30,
141 },
142 .hw.init = &(struct clk_init_data){
143 .name = "ao_32k",
144 .ops = &clk_regmap_gate_ops,
145 .parent_names = (const char *[]){ "ao_32k_sel" },
39 .num_parents = 1, 146 .num_parents = 1,
40 .flags = CLK_IGNORE_UNUSED, 147 .flags = CLK_SET_RATE_PARENT,
148 },
149};
150
151static struct clk_regmap ao_cts_rtc_oscin = {
152 .data = &(struct clk_regmap_mux_data) {
153 .offset = AO_RTI_PWR_CNTL_REG0,
154 .mask = 0x7,
155 .shift = 10,
156 .table = (u32[]){ 1, 2, 3, 4 },
157 .flags = CLK_MUX_ROUND_CLOSEST,
158 },
159 .hw.init = &(struct clk_init_data){
160 .name = "ao_cts_rtc_oscin",
161 .ops = &clk_regmap_mux_ops,
162 .parent_names = (const char *[]){ IN_PREFIX "ext-32k-0",
163 IN_PREFIX "ext-32k-1",
164 IN_PREFIX "ext-32k-2",
165 "ao_32k" },
166 .num_parents = 4,
167 .flags = CLK_SET_RATE_PARENT,
168 },
169};
170
171static struct clk_regmap ao_clk81 = {
172 .data = &(struct clk_regmap_mux_data) {
173 .offset = AO_RTI_PWR_CNTL_REG0,
174 .mask = 0x1,
175 .shift = 0,
176 .flags = CLK_MUX_ROUND_CLOSEST,
177 },
178 .hw.init = &(struct clk_init_data){
179 .name = "ao_clk81",
180 .ops = &clk_regmap_mux_ro_ops,
181 .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
182 "ao_cts_rtc_oscin" },
183 .num_parents = 2,
184 .flags = CLK_SET_RATE_PARENT,
185 },
186};
187
188static struct clk_regmap ao_cts_cec = {
189 .data = &(struct clk_regmap_mux_data) {
190 .offset = AO_CRT_CLK_CNTL1,
191 .mask = 0x1,
192 .shift = 27,
193 .flags = CLK_MUX_ROUND_CLOSEST,
194 },
195 .hw.init = &(struct clk_init_data){
196 .name = "ao_cts_cec",
197 .ops = &clk_regmap_mux_ops,
198 /*
199 * FIXME: The 'fixme' parent obviously does not exist.
200 *
201 * ATM, CCF won't call get_parent() if num_parents is 1. It
202 * does not allow NULL as a parent name either.
203 *
204 * On this particular mux, we only know the input #1 parent
205 * but, on boot, unknown input #0 is set, so it is critical
206 * to call .get_parent() on it
207 *
208 * Until CCF gets fixed, adding this fake parent that won't
209 * ever be registered should work around the problem
210 */
211 .parent_names = (const char *[]){ "fixme",
212 "ao_cts_rtc_oscin" },
213 .num_parents = 2,
214 .flags = CLK_SET_RATE_PARENT,
41 }, 215 },
42}; 216};
43 217
@@ -50,13 +224,21 @@ static const unsigned int gxbb_aoclk_reset[] = {
50 [RESET_AO_IR_BLASTER] = 23, 224 [RESET_AO_IR_BLASTER] = 23,
51}; 225};
52 226
53static struct clk_regmap *gxbb_aoclk_gate[] = { 227static struct clk_regmap *gxbb_aoclk[] = {
54 [CLKID_AO_REMOTE] = &remote_ao, 228 &remote_ao,
55 [CLKID_AO_I2C_MASTER] = &i2c_master_ao, 229 &i2c_master_ao,
56 [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao, 230 &i2c_slave_ao,
57 [CLKID_AO_UART1] = &uart1_ao, 231 &uart1_ao,
58 [CLKID_AO_UART2] = &uart2_ao, 232 &uart2_ao,
59 [CLKID_AO_IR_BLASTER] = &ir_blaster_ao, 233 &ir_blaster_ao,
234 &ao_cts_oscin,
235 &ao_32k_pre,
236 &ao_32k_div,
237 &ao_32k_sel,
238 &ao_32k,
239 &ao_cts_rtc_oscin,
240 &ao_clk81,
241 &ao_cts_cec,
60}; 242};
61 243
62static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = { 244static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
@@ -67,52 +249,38 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
67 [CLKID_AO_UART1] = &uart1_ao.hw, 249 [CLKID_AO_UART1] = &uart1_ao.hw,
68 [CLKID_AO_UART2] = &uart2_ao.hw, 250 [CLKID_AO_UART2] = &uart2_ao.hw,
69 [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw, 251 [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
70 [CLKID_AO_CEC_32K] = &cec_32k_ao.hw, 252 [CLKID_AO_CEC_32K] = &ao_cts_cec.hw,
253 [CLKID_AO_CTS_OSCIN] = &ao_cts_oscin.hw,
254 [CLKID_AO_32K_PRE] = &ao_32k_pre.hw,
255 [CLKID_AO_32K_DIV] = &ao_32k_div.hw,
256 [CLKID_AO_32K_SEL] = &ao_32k_sel.hw,
257 [CLKID_AO_32K] = &ao_32k.hw,
258 [CLKID_AO_CTS_RTC_OSCIN] = &ao_cts_rtc_oscin.hw,
259 [CLKID_AO_CLK81] = &ao_clk81.hw,
71 }, 260 },
72 .num = NR_CLKS, 261 .num = NR_CLKS,
73}; 262};
74 263
75static int gxbb_register_cec_ao_32k(struct platform_device *pdev) 264static const struct meson_aoclk_input gxbb_aoclk_inputs[] = {
76{ 265 { .name = "xtal", .required = true, },
77 struct device *dev = &pdev->dev; 266 { .name = "mpeg-clk", .required = true, },
78 struct regmap *regmap; 267 {. name = "ext-32k-0", .required = false, },
79 int ret; 268 {. name = "ext-32k-1", .required = false, },
80 269 {. name = "ext-32k-2", .required = false, },
81 regmap = syscon_node_to_regmap(of_get_parent(dev->of_node)); 270};
82 if (IS_ERR(regmap)) {
83 dev_err(dev, "failed to get regmap\n");
84 return PTR_ERR(regmap);
85 }
86
87 /* Specific clocks */
88 cec_32k_ao.regmap = regmap;
89 ret = devm_clk_hw_register(dev, &cec_32k_ao.hw);
90 if (ret) {
91 dev_err(&pdev->dev, "clk cec_32k_ao register failed.\n");
92 return ret;
93 }
94
95 return 0;
96}
97 271
98static const struct meson_aoclk_data gxbb_aoclkc_data = { 272static const struct meson_aoclk_data gxbb_aoclkc_data = {
99 .reset_reg = AO_RTI_GEN_CNTL_REG0, 273 .reset_reg = AO_RTI_GEN_CNTL_REG0,
100 .num_reset = ARRAY_SIZE(gxbb_aoclk_reset), 274 .num_reset = ARRAY_SIZE(gxbb_aoclk_reset),
101 .reset = gxbb_aoclk_reset, 275 .reset = gxbb_aoclk_reset,
102 .num_clks = ARRAY_SIZE(gxbb_aoclk_gate), 276 .num_clks = ARRAY_SIZE(gxbb_aoclk),
103 .clks = gxbb_aoclk_gate, 277 .clks = gxbb_aoclk,
104 .hw_data = &gxbb_aoclk_onecell_data, 278 .hw_data = &gxbb_aoclk_onecell_data,
279 .inputs = gxbb_aoclk_inputs,
280 .num_inputs = ARRAY_SIZE(gxbb_aoclk_inputs),
281 .input_prefix = IN_PREFIX,
105}; 282};
106 283
107static int gxbb_aoclkc_probe(struct platform_device *pdev)
108{
109 int ret = gxbb_register_cec_ao_32k(pdev);
110 if (ret)
111 return ret;
112
113 return meson_aoclkc_probe(pdev);
114}
115
116static const struct of_device_id gxbb_aoclkc_match_table[] = { 284static const struct of_device_id gxbb_aoclkc_match_table[] = {
117 { 285 {
118 .compatible = "amlogic,meson-gx-aoclkc", 286 .compatible = "amlogic,meson-gx-aoclkc",
@@ -122,7 +290,7 @@ static const struct of_device_id gxbb_aoclkc_match_table[] = {
122}; 290};
123 291
124static struct platform_driver gxbb_aoclkc_driver = { 292static struct platform_driver gxbb_aoclkc_driver = {
125 .probe = gxbb_aoclkc_probe, 293 .probe = meson_aoclkc_probe,
126 .driver = { 294 .driver = {
127 .name = "gxbb-aoclkc", 295 .name = "gxbb-aoclkc",
128 .of_match_table = gxbb_aoclkc_match_table, 296 .of_match_table = gxbb_aoclkc_match_table,
diff --git a/drivers/clk/meson/gxbb-aoclk.h b/drivers/clk/meson/gxbb-aoclk.h
index c514493d989a..1db16f9b37d4 100644
--- a/drivers/clk/meson/gxbb-aoclk.h
+++ b/drivers/clk/meson/gxbb-aoclk.h
@@ -7,25 +7,7 @@
7#ifndef __GXBB_AOCLKC_H 7#ifndef __GXBB_AOCLKC_H
8#define __GXBB_AOCLKC_H 8#define __GXBB_AOCLKC_H
9 9
10#define NR_CLKS 7 10#define NR_CLKS 14
11
12/* AO Configuration Clock registers offsets */
13#define AO_RTI_PWR_CNTL_REG1 0x0c
14#define AO_RTI_PWR_CNTL_REG0 0x10
15#define AO_RTI_GEN_CNTL_REG0 0x40
16#define AO_OSCIN_CNTL 0x58
17#define AO_CRT_CLK_CNTL1 0x68
18#define AO_RTC_ALT_CLK_CNTL0 0x94
19#define AO_RTC_ALT_CLK_CNTL1 0x98
20
21struct aoclk_cec_32k {
22 struct clk_hw hw;
23 struct regmap *regmap;
24};
25
26#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
27
28extern const struct clk_ops meson_aoclk_cec_32k_ops;
29 11
30#include <dt-bindings/clock/gxbb-aoclkc.h> 12#include <dt-bindings/clock/gxbb-aoclkc.h>
31#include <dt-bindings/reset/gxbb-aoclkc.h> 13#include <dt-bindings/reset/gxbb-aoclkc.h>
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 65f2599e5243..04df2e208ed6 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -4,17 +4,20 @@
4 * Michael Turquette <mturquette@baylibre.com> 4 * Michael Turquette <mturquette@baylibre.com>
5 */ 5 */
6 6
7#include <linux/clk.h>
8#include <linux/clk-provider.h> 7#include <linux/clk-provider.h>
9#include <linux/init.h> 8#include <linux/init.h>
10#include <linux/of_device.h> 9#include <linux/of_device.h>
11#include <linux/mfd/syscon.h>
12#include <linux/platform_device.h> 10#include <linux/platform_device.h>
13#include <linux/regmap.h>
14 11
15#include "clkc.h"
16#include "gxbb.h" 12#include "gxbb.h"
13#include "clk-input.h"
17#include "clk-regmap.h" 14#include "clk-regmap.h"
15#include "clk-pll.h"
16#include "clk-mpll.h"
17#include "meson-eeclk.h"
18#include "vid-pll-div.h"
19
20#define IN_PREFIX "ee-in-"
18 21
19static DEFINE_SPINLOCK(meson_clk_lock); 22static DEFINE_SPINLOCK(meson_clk_lock);
20 23
@@ -118,7 +121,7 @@ static struct clk_regmap gxbb_fixed_pll_dco = {
118 .hw.init = &(struct clk_init_data){ 121 .hw.init = &(struct clk_init_data){
119 .name = "fixed_pll_dco", 122 .name = "fixed_pll_dco",
120 .ops = &meson_clk_pll_ro_ops, 123 .ops = &meson_clk_pll_ro_ops,
121 .parent_names = (const char *[]){ "xtal" }, 124 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
122 .num_parents = 1, 125 .num_parents = 1,
123 }, 126 },
124}; 127};
@@ -148,7 +151,7 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
148 .hw.init = &(struct clk_init_data){ 151 .hw.init = &(struct clk_init_data){
149 .name = "hdmi_pll_pre_mult", 152 .name = "hdmi_pll_pre_mult",
150 .ops = &clk_fixed_factor_ops, 153 .ops = &clk_fixed_factor_ops,
151 .parent_names = (const char *[]){ "xtal" }, 154 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
152 .num_parents = 1, 155 .num_parents = 1,
153 }, 156 },
154}; 157};
@@ -241,7 +244,7 @@ static struct clk_regmap gxl_hdmi_pll_dco = {
241 .hw.init = &(struct clk_init_data){ 244 .hw.init = &(struct clk_init_data){
242 .name = "hdmi_pll_dco", 245 .name = "hdmi_pll_dco",
243 .ops = &meson_clk_pll_ro_ops, 246 .ops = &meson_clk_pll_ro_ops,
244 .parent_names = (const char *[]){ "xtal" }, 247 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
245 .num_parents = 1, 248 .num_parents = 1,
246 /* 249 /*
247 * Display directly handle hdmi pll registers ATM, we need 250 * Display directly handle hdmi pll registers ATM, we need
@@ -378,7 +381,7 @@ static struct clk_regmap gxbb_sys_pll_dco = {
378 .hw.init = &(struct clk_init_data){ 381 .hw.init = &(struct clk_init_data){
379 .name = "sys_pll_dco", 382 .name = "sys_pll_dco",
380 .ops = &meson_clk_pll_ro_ops, 383 .ops = &meson_clk_pll_ro_ops,
381 .parent_names = (const char *[]){ "xtal" }, 384 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
382 .num_parents = 1, 385 .num_parents = 1,
383 }, 386 },
384}; 387};
@@ -439,7 +442,7 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
439 .hw.init = &(struct clk_init_data){ 442 .hw.init = &(struct clk_init_data){
440 .name = "gp0_pll_dco", 443 .name = "gp0_pll_dco",
441 .ops = &meson_clk_pll_ops, 444 .ops = &meson_clk_pll_ops,
442 .parent_names = (const char *[]){ "xtal" }, 445 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
443 .num_parents = 1, 446 .num_parents = 1,
444 }, 447 },
445}; 448};
@@ -491,7 +494,7 @@ static struct clk_regmap gxl_gp0_pll_dco = {
491 .hw.init = &(struct clk_init_data){ 494 .hw.init = &(struct clk_init_data){
492 .name = "gp0_pll_dco", 495 .name = "gp0_pll_dco",
493 .ops = &meson_clk_pll_ops, 496 .ops = &meson_clk_pll_ops,
494 .parent_names = (const char *[]){ "xtal" }, 497 .parent_names = (const char *[]){ IN_PREFIX "xtal" },
495 .num_parents = 1, 498 .num_parents = 1,
496 }, 499 },
497}; 500};
@@ -789,7 +792,7 @@ static struct clk_regmap gxbb_mpll2 = {
789 792
790static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 }; 793static u32 mux_table_clk81[] = { 0, 2, 3, 4, 5, 6, 7 };
791static const char * const clk81_parent_names[] = { 794static const char * const clk81_parent_names[] = {
792 "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4", 795 IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
793 "fclk_div3", "fclk_div5" 796 "fclk_div3", "fclk_div5"
794}; 797};
795 798
@@ -852,7 +855,7 @@ static struct clk_regmap gxbb_sar_adc_clk_sel = {
852 .name = "sar_adc_clk_sel", 855 .name = "sar_adc_clk_sel",
853 .ops = &clk_regmap_mux_ops, 856 .ops = &clk_regmap_mux_ops,
854 /* NOTE: The datasheet doesn't list the parents for bit 10 */ 857 /* NOTE: The datasheet doesn't list the parents for bit 10 */
855 .parent_names = (const char *[]){ "xtal", "clk81", }, 858 .parent_names = (const char *[]){ IN_PREFIX "xtal", "clk81", },
856 .num_parents = 2, 859 .num_parents = 2,
857 }, 860 },
858}; 861};
@@ -891,7 +894,7 @@ static struct clk_regmap gxbb_sar_adc_clk = {
891 */ 894 */
892 895
893static const char * const gxbb_mali_0_1_parent_names[] = { 896static const char * const gxbb_mali_0_1_parent_names[] = {
894 "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7", 897 IN_PREFIX "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
895 "fclk_div4", "fclk_div3", "fclk_div5" 898 "fclk_div4", "fclk_div3", "fclk_div5"
896}; 899};
897 900
@@ -1153,7 +1156,7 @@ static struct clk_regmap gxbb_32k_clk = {
1153}; 1156};
1154 1157
1155static const char * const gxbb_32k_clk_parent_names[] = { 1158static const char * const gxbb_32k_clk_parent_names[] = {
1156 "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5" 1159 IN_PREFIX "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
1157}; 1160};
1158 1161
1159static struct clk_regmap gxbb_32k_clk_sel = { 1162static struct clk_regmap gxbb_32k_clk_sel = {
@@ -1172,7 +1175,7 @@ static struct clk_regmap gxbb_32k_clk_sel = {
1172}; 1175};
1173 1176
1174static const char * const gxbb_sd_emmc_clk0_parent_names[] = { 1177static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
1175 "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7", 1178 IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
1176 1179
1177 /* 1180 /*
1178 * Following these parent clocks, we should also have had mpll2, mpll3 1181 * Following these parent clocks, we should also have had mpll2, mpll3
@@ -2138,7 +2141,7 @@ static struct clk_regmap gxbb_hdmi_tx = {
2138/* HDMI Clocks */ 2141/* HDMI Clocks */
2139 2142
2140static const char * const gxbb_hdmi_parent_names[] = { 2143static const char * const gxbb_hdmi_parent_names[] = {
2141 "xtal", "fclk_div4", "fclk_div3", "fclk_div5" 2144 IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
2142}; 2145};
2143 2146
2144static struct clk_regmap gxbb_hdmi_sel = { 2147static struct clk_regmap gxbb_hdmi_sel = {
@@ -2285,7 +2288,7 @@ static struct clk_regmap gxbb_vdec_hevc = {
2285static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8, 2288static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
2286 9, 10, 11, 13, 14, }; 2289 9, 10, 11, 13, 14, };
2287static const char * const gen_clk_parent_names[] = { 2290static const char * const gen_clk_parent_names[] = {
2288 "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2", 2291 IN_PREFIX "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2",
2289 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll", 2292 "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
2290}; 2293};
2291 2294
@@ -2854,6 +2857,192 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
2854}; 2857};
2855 2858
2856static struct clk_regmap *const gxbb_clk_regmaps[] = { 2859static struct clk_regmap *const gxbb_clk_regmaps[] = {
2860 &gxbb_clk81,
2861 &gxbb_ddr,
2862 &gxbb_dos,
2863 &gxbb_isa,
2864 &gxbb_pl301,
2865 &gxbb_periphs,
2866 &gxbb_spicc,
2867 &gxbb_i2c,
2868 &gxbb_sar_adc,
2869 &gxbb_smart_card,
2870 &gxbb_rng0,
2871 &gxbb_uart0,
2872 &gxbb_sdhc,
2873 &gxbb_stream,
2874 &gxbb_async_fifo,
2875 &gxbb_sdio,
2876 &gxbb_abuf,
2877 &gxbb_hiu_iface,
2878 &gxbb_assist_misc,
2879 &gxbb_spi,
2880 &gxbb_i2s_spdif,
2881 &gxbb_eth,
2882 &gxbb_demux,
2883 &gxbb_aiu_glue,
2884 &gxbb_iec958,
2885 &gxbb_i2s_out,
2886 &gxbb_amclk,
2887 &gxbb_aififo2,
2888 &gxbb_mixer,
2889 &gxbb_mixer_iface,
2890 &gxbb_adc,
2891 &gxbb_blkmv,
2892 &gxbb_aiu,
2893 &gxbb_uart1,
2894 &gxbb_g2d,
2895 &gxbb_usb0,
2896 &gxbb_usb1,
2897 &gxbb_reset,
2898 &gxbb_nand,
2899 &gxbb_dos_parser,
2900 &gxbb_usb,
2901 &gxbb_vdin1,
2902 &gxbb_ahb_arb0,
2903 &gxbb_efuse,
2904 &gxbb_boot_rom,
2905 &gxbb_ahb_data_bus,
2906 &gxbb_ahb_ctrl_bus,
2907 &gxbb_hdmi_intr_sync,
2908 &gxbb_hdmi_pclk,
2909 &gxbb_usb1_ddr_bridge,
2910 &gxbb_usb0_ddr_bridge,
2911 &gxbb_mmc_pclk,
2912 &gxbb_dvin,
2913 &gxbb_uart2,
2914 &gxbb_sana,
2915 &gxbb_vpu_intr,
2916 &gxbb_sec_ahb_ahb3_bridge,
2917 &gxbb_clk81_a53,
2918 &gxbb_vclk2_venci0,
2919 &gxbb_vclk2_venci1,
2920 &gxbb_vclk2_vencp0,
2921 &gxbb_vclk2_vencp1,
2922 &gxbb_gclk_venci_int0,
2923 &gxbb_gclk_vencp_int,
2924 &gxbb_dac_clk,
2925 &gxbb_aoclk_gate,
2926 &gxbb_iec958_gate,
2927 &gxbb_enc480p,
2928 &gxbb_rng1,
2929 &gxbb_gclk_venci_int1,
2930 &gxbb_vclk2_venclmcc,
2931 &gxbb_vclk2_vencl,
2932 &gxbb_vclk_other,
2933 &gxbb_edp,
2934 &gxbb_ao_media_cpu,
2935 &gxbb_ao_ahb_sram,
2936 &gxbb_ao_ahb_bus,
2937 &gxbb_ao_iface,
2938 &gxbb_ao_i2c,
2939 &gxbb_emmc_a,
2940 &gxbb_emmc_b,
2941 &gxbb_emmc_c,
2942 &gxbb_sar_adc_clk,
2943 &gxbb_mali_0,
2944 &gxbb_mali_1,
2945 &gxbb_cts_amclk,
2946 &gxbb_cts_mclk_i958,
2947 &gxbb_32k_clk,
2948 &gxbb_sd_emmc_a_clk0,
2949 &gxbb_sd_emmc_b_clk0,
2950 &gxbb_sd_emmc_c_clk0,
2951 &gxbb_vpu_0,
2952 &gxbb_vpu_1,
2953 &gxbb_vapb_0,
2954 &gxbb_vapb_1,
2955 &gxbb_vapb,
2956 &gxbb_mpeg_clk_div,
2957 &gxbb_sar_adc_clk_div,
2958 &gxbb_mali_0_div,
2959 &gxbb_mali_1_div,
2960 &gxbb_cts_mclk_i958_div,
2961 &gxbb_32k_clk_div,
2962 &gxbb_sd_emmc_a_clk0_div,
2963 &gxbb_sd_emmc_b_clk0_div,
2964 &gxbb_sd_emmc_c_clk0_div,
2965 &gxbb_vpu_0_div,
2966 &gxbb_vpu_1_div,
2967 &gxbb_vapb_0_div,
2968 &gxbb_vapb_1_div,
2969 &gxbb_mpeg_clk_sel,
2970 &gxbb_sar_adc_clk_sel,
2971 &gxbb_mali_0_sel,
2972 &gxbb_mali_1_sel,
2973 &gxbb_mali,
2974 &gxbb_cts_amclk_sel,
2975 &gxbb_cts_mclk_i958_sel,
2976 &gxbb_cts_i958,
2977 &gxbb_32k_clk_sel,
2978 &gxbb_sd_emmc_a_clk0_sel,
2979 &gxbb_sd_emmc_b_clk0_sel,
2980 &gxbb_sd_emmc_c_clk0_sel,
2981 &gxbb_vpu_0_sel,
2982 &gxbb_vpu_1_sel,
2983 &gxbb_vpu,
2984 &gxbb_vapb_0_sel,
2985 &gxbb_vapb_1_sel,
2986 &gxbb_vapb_sel,
2987 &gxbb_mpll0,
2988 &gxbb_mpll1,
2989 &gxbb_mpll2,
2990 &gxbb_mpll0_div,
2991 &gxbb_mpll1_div,
2992 &gxbb_mpll2_div,
2993 &gxbb_cts_amclk_div,
2994 &gxbb_fixed_pll,
2995 &gxbb_sys_pll,
2996 &gxbb_mpll_prediv,
2997 &gxbb_fclk_div2,
2998 &gxbb_fclk_div3,
2999 &gxbb_fclk_div4,
3000 &gxbb_fclk_div5,
3001 &gxbb_fclk_div7,
3002 &gxbb_vdec_1_sel,
3003 &gxbb_vdec_1_div,
3004 &gxbb_vdec_1,
3005 &gxbb_vdec_hevc_sel,
3006 &gxbb_vdec_hevc_div,
3007 &gxbb_vdec_hevc,
3008 &gxbb_gen_clk_sel,
3009 &gxbb_gen_clk_div,
3010 &gxbb_gen_clk,
3011 &gxbb_fixed_pll_dco,
3012 &gxbb_sys_pll_dco,
3013 &gxbb_gp0_pll,
3014 &gxbb_vid_pll,
3015 &gxbb_vid_pll_sel,
3016 &gxbb_vid_pll_div,
3017 &gxbb_vclk,
3018 &gxbb_vclk_sel,
3019 &gxbb_vclk_div,
3020 &gxbb_vclk_input,
3021 &gxbb_vclk_div1,
3022 &gxbb_vclk_div2_en,
3023 &gxbb_vclk_div4_en,
3024 &gxbb_vclk_div6_en,
3025 &gxbb_vclk_div12_en,
3026 &gxbb_vclk2,
3027 &gxbb_vclk2_sel,
3028 &gxbb_vclk2_div,
3029 &gxbb_vclk2_input,
3030 &gxbb_vclk2_div1,
3031 &gxbb_vclk2_div2_en,
3032 &gxbb_vclk2_div4_en,
3033 &gxbb_vclk2_div6_en,
3034 &gxbb_vclk2_div12_en,
3035 &gxbb_cts_enci,
3036 &gxbb_cts_enci_sel,
3037 &gxbb_cts_encp,
3038 &gxbb_cts_encp_sel,
3039 &gxbb_cts_vdac,
3040 &gxbb_cts_vdac_sel,
3041 &gxbb_hdmi_tx,
3042 &gxbb_hdmi_tx_sel,
3043 &gxbb_hdmi_sel,
3044 &gxbb_hdmi_div,
3045 &gxbb_hdmi,
2857 &gxbb_gp0_pll_dco, 3046 &gxbb_gp0_pll_dco,
2858 &gxbb_hdmi_pll, 3047 &gxbb_hdmi_pll,
2859 &gxbb_hdmi_pll_od, 3048 &gxbb_hdmi_pll_od,
@@ -2862,14 +3051,6 @@ static struct clk_regmap *const gxbb_clk_regmaps[] = {
2862}; 3051};
2863 3052
2864static struct clk_regmap *const gxl_clk_regmaps[] = { 3053static struct clk_regmap *const gxl_clk_regmaps[] = {
2865 &gxl_gp0_pll_dco,
2866 &gxl_hdmi_pll,
2867 &gxl_hdmi_pll_od,
2868 &gxl_hdmi_pll_od2,
2869 &gxl_hdmi_pll_dco,
2870};
2871
2872static struct clk_regmap *const gx_clk_regmaps[] = {
2873 &gxbb_clk81, 3054 &gxbb_clk81,
2874 &gxbb_ddr, 3055 &gxbb_ddr,
2875 &gxbb_dos, 3056 &gxbb_dos,
@@ -3056,23 +3237,22 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
3056 &gxbb_hdmi_sel, 3237 &gxbb_hdmi_sel,
3057 &gxbb_hdmi_div, 3238 &gxbb_hdmi_div,
3058 &gxbb_hdmi, 3239 &gxbb_hdmi,
3240 &gxl_gp0_pll_dco,
3241 &gxl_hdmi_pll,
3242 &gxl_hdmi_pll_od,
3243 &gxl_hdmi_pll_od2,
3244 &gxl_hdmi_pll_dco,
3059}; 3245};
3060 3246
3061struct clkc_data { 3247static const struct meson_eeclkc_data gxbb_clkc_data = {
3062 struct clk_regmap *const *regmap_clks;
3063 unsigned int regmap_clks_count;
3064 struct clk_hw_onecell_data *hw_onecell_data;
3065};
3066
3067static const struct clkc_data gxbb_clkc_data = {
3068 .regmap_clks = gxbb_clk_regmaps, 3248 .regmap_clks = gxbb_clk_regmaps,
3069 .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps), 3249 .regmap_clk_num = ARRAY_SIZE(gxbb_clk_regmaps),
3070 .hw_onecell_data = &gxbb_hw_onecell_data, 3250 .hw_onecell_data = &gxbb_hw_onecell_data,
3071}; 3251};
3072 3252
3073static const struct clkc_data gxl_clkc_data = { 3253static const struct meson_eeclkc_data gxl_clkc_data = {
3074 .regmap_clks = gxl_clk_regmaps, 3254 .regmap_clks = gxl_clk_regmaps,
3075 .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps), 3255 .regmap_clk_num = ARRAY_SIZE(gxl_clk_regmaps),
3076 .hw_onecell_data = &gxl_hw_onecell_data, 3256 .hw_onecell_data = &gxl_hw_onecell_data,
3077}; 3257};
3078 3258
@@ -3082,52 +3262,8 @@ static const struct of_device_id clkc_match_table[] = {
3082 {}, 3262 {},
3083}; 3263};
3084 3264
3085static int gxbb_clkc_probe(struct platform_device *pdev)
3086{
3087 const struct clkc_data *clkc_data;
3088 struct regmap *map;
3089 int ret, i;
3090 struct device *dev = &pdev->dev;
3091
3092 clkc_data = of_device_get_match_data(dev);
3093 if (!clkc_data)
3094 return -EINVAL;
3095
3096 /* Get the hhi system controller node if available */
3097 map = syscon_node_to_regmap(of_get_parent(dev->of_node));
3098 if (IS_ERR(map)) {
3099 dev_err(dev, "failed to get HHI regmap\n");
3100 return PTR_ERR(map);
3101 }
3102
3103 /* Populate regmap for the common regmap backed clocks */
3104 for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
3105 gx_clk_regmaps[i]->map = map;
3106
3107 /* Populate regmap for soc specific clocks */
3108 for (i = 0; i < clkc_data->regmap_clks_count; i++)
3109 clkc_data->regmap_clks[i]->map = map;
3110
3111 /* Register all clks */
3112 for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
3113 /* array might be sparse */
3114 if (!clkc_data->hw_onecell_data->hws[i])
3115 continue;
3116
3117 ret = devm_clk_hw_register(dev,
3118 clkc_data->hw_onecell_data->hws[i]);
3119 if (ret) {
3120 dev_err(dev, "Clock registration failed\n");
3121 return ret;
3122 }
3123 }
3124
3125 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
3126 clkc_data->hw_onecell_data);
3127}
3128
3129static struct platform_driver gxbb_driver = { 3265static struct platform_driver gxbb_driver = {
3130 .probe = gxbb_clkc_probe, 3266 .probe = meson_eeclkc_probe,
3131 .driver = { 3267 .driver = {
3132 .name = "gxbb-clkc", 3268 .name = "gxbb-clkc",
3133 .of_match_table = clkc_match_table, 3269 .of_match_table = clkc_match_table,
diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c
index f965845917e3..b67951909e04 100644
--- a/drivers/clk/meson/meson-aoclk.c
+++ b/drivers/clk/meson/meson-aoclk.c
@@ -14,9 +14,11 @@
14#include <linux/reset-controller.h> 14#include <linux/reset-controller.h>
15#include <linux/mfd/syscon.h> 15#include <linux/mfd/syscon.h>
16#include <linux/of_device.h> 16#include <linux/of_device.h>
17#include "clk-regmap.h" 17#include <linux/slab.h>
18#include "meson-aoclk.h" 18#include "meson-aoclk.h"
19 19
20#include "clk-input.h"
21
20static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev, 22static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev,
21 unsigned long id) 23 unsigned long id)
22{ 24{
@@ -31,6 +33,37 @@ static const struct reset_control_ops meson_aoclk_reset_ops = {
31 .reset = meson_aoclk_do_reset, 33 .reset = meson_aoclk_do_reset,
32}; 34};
33 35
36static int meson_aoclkc_register_inputs(struct device *dev,
37 struct meson_aoclk_data *data)
38{
39 struct clk_hw *hw;
40 char *str;
41 int i;
42
43 for (i = 0; i < data->num_inputs; i++) {
44 const struct meson_aoclk_input *in = &data->inputs[i];
45
46 str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix,
47 in->name);
48 if (!str)
49 return -ENOMEM;
50
51 hw = meson_clk_hw_register_input(dev, in->name, str, 0);
52 kfree(str);
53
54 if (IS_ERR(hw)) {
55 if (!in->required && PTR_ERR(hw) == -ENOENT)
56 continue;
57 else if (PTR_ERR(hw) != -EPROBE_DEFER)
58 dev_err(dev, "failed to register input %s\n",
59 in->name);
60 return PTR_ERR(hw);
61 }
62 }
63
64 return 0;
65}
66
34int meson_aoclkc_probe(struct platform_device *pdev) 67int meson_aoclkc_probe(struct platform_device *pdev)
35{ 68{
36 struct meson_aoclk_reset_controller *rstc; 69 struct meson_aoclk_reset_controller *rstc;
@@ -53,6 +86,10 @@ int meson_aoclkc_probe(struct platform_device *pdev)
53 return PTR_ERR(regmap); 86 return PTR_ERR(regmap);
54 } 87 }
55 88
89 ret = meson_aoclkc_register_inputs(dev, data);
90 if (ret)
91 return ret;
92
56 /* Reset Controller */ 93 /* Reset Controller */
57 rstc->data = data; 94 rstc->data = data;
58 rstc->regmap = regmap; 95 rstc->regmap = regmap;
@@ -65,15 +102,20 @@ int meson_aoclkc_probe(struct platform_device *pdev)
65 return ret; 102 return ret;
66 } 103 }
67 104
68 /* 105 /* Populate regmap */
69 * Populate regmap and register all clks 106 for (clkid = 0; clkid < data->num_clks; clkid++)
70 */
71 for (clkid = 0; clkid < data->num_clks; clkid++) {
72 data->clks[clkid]->map = regmap; 107 data->clks[clkid]->map = regmap;
73 108
109 /* Register all clks */
110 for (clkid = 0; clkid < data->hw_data->num; clkid++) {
111 if (!data->hw_data->hws[clkid])
112 continue;
113
74 ret = devm_clk_hw_register(dev, data->hw_data->hws[clkid]); 114 ret = devm_clk_hw_register(dev, data->hw_data->hws[clkid]);
75 if (ret) 115 if (ret) {
116 dev_err(dev, "Clock registration failed\n");
76 return ret; 117 return ret;
118 }
77 } 119 }
78 120
79 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, 121 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
diff --git a/drivers/clk/meson/meson-aoclk.h b/drivers/clk/meson/meson-aoclk.h
index ab2819e88922..999cde3868f7 100644
--- a/drivers/clk/meson/meson-aoclk.h
+++ b/drivers/clk/meson/meson-aoclk.h
@@ -11,16 +11,27 @@
11#ifndef __MESON_AOCLK_H__ 11#ifndef __MESON_AOCLK_H__
12#define __MESON_AOCLK_H__ 12#define __MESON_AOCLK_H__
13 13
14#include <linux/clk-provider.h>
14#include <linux/platform_device.h> 15#include <linux/platform_device.h>
16#include <linux/regmap.h>
15#include <linux/reset-controller.h> 17#include <linux/reset-controller.h>
18
16#include "clk-regmap.h" 19#include "clk-regmap.h"
17 20
21struct meson_aoclk_input {
22 const char *name;
23 bool required;
24};
25
18struct meson_aoclk_data { 26struct meson_aoclk_data {
19 const unsigned int reset_reg; 27 const unsigned int reset_reg;
20 const int num_reset; 28 const int num_reset;
21 const unsigned int *reset; 29 const unsigned int *reset;
22 int num_clks; 30 const int num_clks;
23 struct clk_regmap **clks; 31 struct clk_regmap **clks;
32 const int num_inputs;
33 const struct meson_aoclk_input *inputs;
34 const char *input_prefix;
24 const struct clk_hw_onecell_data *hw_data; 35 const struct clk_hw_onecell_data *hw_data;
25}; 36};
26 37
diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c
new file mode 100644
index 000000000000..37a34c9c3885
--- /dev/null
+++ b/drivers/clk/meson/meson-eeclk.c
@@ -0,0 +1,63 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#include <linux/clk-provider.h>
8#include <linux/of_device.h>
9#include <linux/platform_device.h>
10#include <linux/mfd/syscon.h>
11#include <linux/regmap.h>
12
13#include "clk-input.h"
14#include "clk-regmap.h"
15#include "meson-eeclk.h"
16
17int meson_eeclkc_probe(struct platform_device *pdev)
18{
19 const struct meson_eeclkc_data *data;
20 struct device *dev = &pdev->dev;
21 struct clk_hw *input;
22 struct regmap *map;
23 int ret, i;
24
25 data = of_device_get_match_data(dev);
26 if (!data)
27 return -EINVAL;
28
29 /* Get the hhi system controller node */
30 map = syscon_node_to_regmap(of_get_parent(dev->of_node));
31 if (IS_ERR(map)) {
32 dev_err(dev,
33 "failed to get HHI regmap\n");
34 return PTR_ERR(map);
35 }
36
37 input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0);
38 if (IS_ERR(input)) {
39 ret = PTR_ERR(input);
40 if (ret != -EPROBE_DEFER)
41 dev_err(dev, "failed to get input clock");
42 return ret;
43 }
44
45 /* Populate regmap for the regmap backed clocks */
46 for (i = 0; i < data->regmap_clk_num; i++)
47 data->regmap_clks[i]->map = map;
48
49 for (i = 0; i < data->hw_onecell_data->num; i++) {
50 /* array might be sparse */
51 if (!data->hw_onecell_data->hws[i])
52 continue;
53
54 ret = devm_clk_hw_register(dev, data->hw_onecell_data->hws[i]);
55 if (ret) {
56 dev_err(dev, "Clock registration failed\n");
57 return ret;
58 }
59 }
60
61 return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
62 data->hw_onecell_data);
63}
diff --git a/drivers/clk/meson/meson-eeclk.h b/drivers/clk/meson/meson-eeclk.h
new file mode 100644
index 000000000000..1b809b1419fe
--- /dev/null
+++ b/drivers/clk/meson/meson-eeclk.h
@@ -0,0 +1,25 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_CLKC_H
8#define __MESON_CLKC_H
9
10#include <linux/clk-provider.h>
11#include "clk-regmap.h"
12
13#define IN_PREFIX "ee-in-"
14
15struct platform_device;
16
17struct meson_eeclkc_data {
18 struct clk_regmap *const *regmap_clks;
19 unsigned int regmap_clk_num;
20 struct clk_hw_onecell_data *hw_onecell_data;
21};
22
23int meson_eeclkc_probe(struct platform_device *pdev);
24
25#endif /* __MESON_CLKC_H */
diff --git a/drivers/clk/meson/meson8b.c b/drivers/clk/meson/meson8b.c
index 950d0e548c75..576ad42252d0 100644
--- a/drivers/clk/meson/meson8b.c
+++ b/drivers/clk/meson/meson8b.c
@@ -16,9 +16,10 @@
16#include <linux/slab.h> 16#include <linux/slab.h>
17#include <linux/regmap.h> 17#include <linux/regmap.h>
18 18
19#include "clkc.h"
20#include "meson8b.h" 19#include "meson8b.h"
21#include "clk-regmap.h" 20#include "clk-regmap.h"
21#include "clk-pll.h"
22#include "clk-mpll.h"
22 23
23static DEFINE_SPINLOCK(meson_clk_lock); 24static DEFINE_SPINLOCK(meson_clk_lock);
24 25
@@ -803,16 +804,16 @@ static struct clk_fixed_factor meson8b_cpu_clk_div8 = {
803 }, 804 },
804}; 805};
805 806
806static u32 mux_table_abp[] = { 1, 2, 3, 4, 5, 6, 7 }; 807static u32 mux_table_apb[] = { 1, 2, 3, 4, 5, 6, 7 };
807static struct clk_regmap meson8b_abp_clk_sel = { 808static struct clk_regmap meson8b_apb_clk_sel = {
808 .data = &(struct clk_regmap_mux_data){ 809 .data = &(struct clk_regmap_mux_data){
809 .offset = HHI_SYS_CPU_CLK_CNTL1, 810 .offset = HHI_SYS_CPU_CLK_CNTL1,
810 .mask = 0x7, 811 .mask = 0x7,
811 .shift = 3, 812 .shift = 3,
812 .table = mux_table_abp, 813 .table = mux_table_apb,
813 }, 814 },
814 .hw.init = &(struct clk_init_data){ 815 .hw.init = &(struct clk_init_data){
815 .name = "abp_clk_sel", 816 .name = "apb_clk_sel",
816 .ops = &clk_regmap_mux_ops, 817 .ops = &clk_regmap_mux_ops,
817 .parent_names = (const char *[]){ "cpu_clk_div2", 818 .parent_names = (const char *[]){ "cpu_clk_div2",
818 "cpu_clk_div3", 819 "cpu_clk_div3",
@@ -825,16 +826,16 @@ static struct clk_regmap meson8b_abp_clk_sel = {
825 }, 826 },
826}; 827};
827 828
828static struct clk_regmap meson8b_abp_clk_gate = { 829static struct clk_regmap meson8b_apb_clk_gate = {
829 .data = &(struct clk_regmap_gate_data){ 830 .data = &(struct clk_regmap_gate_data){
830 .offset = HHI_SYS_CPU_CLK_CNTL1, 831 .offset = HHI_SYS_CPU_CLK_CNTL1,
831 .bit_idx = 16, 832 .bit_idx = 16,
832 .flags = CLK_GATE_SET_TO_DISABLE, 833 .flags = CLK_GATE_SET_TO_DISABLE,
833 }, 834 },
834 .hw.init = &(struct clk_init_data){ 835 .hw.init = &(struct clk_init_data){
835 .name = "abp_clk_dis", 836 .name = "apb_clk_dis",
836 .ops = &clk_regmap_gate_ro_ops, 837 .ops = &clk_regmap_gate_ro_ops,
837 .parent_names = (const char *[]){ "abp_clk_sel" }, 838 .parent_names = (const char *[]){ "apb_clk_sel" },
838 .num_parents = 1, 839 .num_parents = 1,
839 .flags = CLK_SET_RATE_PARENT, 840 .flags = CLK_SET_RATE_PARENT,
840 }, 841 },
@@ -1573,6 +1574,135 @@ static struct clk_regmap meson8b_hdmi_sys = {
1573 }, 1574 },
1574}; 1575};
1575 1576
1577/*
1578 * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
1579 * muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only
1580 * has mali_0 and no glitch-free mux.
1581 */
1582static const char * const meson8b_mali_0_1_parent_names[] = {
1583 "xtal", "mpll2", "mpll1", "fclk_div7", "fclk_div4", "fclk_div3",
1584 "fclk_div5"
1585};
1586
1587static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 };
1588
1589static struct clk_regmap meson8b_mali_0_sel = {
1590 .data = &(struct clk_regmap_mux_data){
1591 .offset = HHI_MALI_CLK_CNTL,
1592 .mask = 0x7,
1593 .shift = 9,
1594 .table = meson8b_mali_0_1_mux_table,
1595 },
1596 .hw.init = &(struct clk_init_data){
1597 .name = "mali_0_sel",
1598 .ops = &clk_regmap_mux_ops,
1599 .parent_names = meson8b_mali_0_1_parent_names,
1600 .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
1601 /*
1602 * Don't propagate rate changes up because the only changeable
1603 * parents are mpll1 and mpll2 but we need those for audio and
1604 * RGMII (Ethernet). We don't want to change the audio or
1605 * Ethernet clocks when setting the GPU frequency.
1606 */
1607 .flags = 0,
1608 },
1609};
1610
1611static struct clk_regmap meson8b_mali_0_div = {
1612 .data = &(struct clk_regmap_div_data){
1613 .offset = HHI_MALI_CLK_CNTL,
1614 .shift = 0,
1615 .width = 7,
1616 },
1617 .hw.init = &(struct clk_init_data){
1618 .name = "mali_0_div",
1619 .ops = &clk_regmap_divider_ops,
1620 .parent_names = (const char *[]){ "mali_0_sel" },
1621 .num_parents = 1,
1622 .flags = CLK_SET_RATE_PARENT,
1623 },
1624};
1625
1626static struct clk_regmap meson8b_mali_0 = {
1627 .data = &(struct clk_regmap_gate_data){
1628 .offset = HHI_MALI_CLK_CNTL,
1629 .bit_idx = 8,
1630 },
1631 .hw.init = &(struct clk_init_data){
1632 .name = "mali_0",
1633 .ops = &clk_regmap_gate_ops,
1634 .parent_names = (const char *[]){ "mali_0_div" },
1635 .num_parents = 1,
1636 .flags = CLK_SET_RATE_PARENT,
1637 },
1638};
1639
1640static struct clk_regmap meson8b_mali_1_sel = {
1641 .data = &(struct clk_regmap_mux_data){
1642 .offset = HHI_MALI_CLK_CNTL,
1643 .mask = 0x7,
1644 .shift = 25,
1645 .table = meson8b_mali_0_1_mux_table,
1646 },
1647 .hw.init = &(struct clk_init_data){
1648 .name = "mali_1_sel",
1649 .ops = &clk_regmap_mux_ops,
1650 .parent_names = meson8b_mali_0_1_parent_names,
1651 .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
1652 /*
1653 * Don't propagate rate changes up because the only changeable
1654 * parents are mpll1 and mpll2 but we need those for audio and
1655 * RGMII (Ethernet). We don't want to change the audio or
1656 * Ethernet clocks when setting the GPU frequency.
1657 */
1658 .flags = 0,
1659 },
1660};
1661
1662static struct clk_regmap meson8b_mali_1_div = {
1663 .data = &(struct clk_regmap_div_data){
1664 .offset = HHI_MALI_CLK_CNTL,
1665 .shift = 16,
1666 .width = 7,
1667 },
1668 .hw.init = &(struct clk_init_data){
1669 .name = "mali_1_div",
1670 .ops = &clk_regmap_divider_ops,
1671 .parent_names = (const char *[]){ "mali_1_sel" },
1672 .num_parents = 1,
1673 .flags = CLK_SET_RATE_PARENT,
1674 },
1675};
1676
1677static struct clk_regmap meson8b_mali_1 = {
1678 .data = &(struct clk_regmap_gate_data){
1679 .offset = HHI_MALI_CLK_CNTL,
1680 .bit_idx = 24,
1681 },
1682 .hw.init = &(struct clk_init_data){
1683 .name = "mali_1",
1684 .ops = &clk_regmap_gate_ops,
1685 .parent_names = (const char *[]){ "mali_1_div" },
1686 .num_parents = 1,
1687 .flags = CLK_SET_RATE_PARENT,
1688 },
1689};
1690
1691static struct clk_regmap meson8b_mali = {
1692 .data = &(struct clk_regmap_mux_data){
1693 .offset = HHI_MALI_CLK_CNTL,
1694 .mask = 1,
1695 .shift = 31,
1696 },
1697 .hw.init = &(struct clk_init_data){
1698 .name = "mali",
1699 .ops = &clk_regmap_mux_ops,
1700 .parent_names = (const char *[]){ "mali_0", "mali_1" },
1701 .num_parents = 2,
1702 .flags = CLK_SET_RATE_PARENT,
1703 },
1704};
1705
1576/* Everything Else (EE) domain gates */ 1706/* Everything Else (EE) domain gates */
1577 1707
1578static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0); 1708static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@@ -1659,6 +1789,188 @@ static MESON_GATE(meson8b_ao_ahb_sram, HHI_GCLK_AO, 1);
1659static MESON_GATE(meson8b_ao_ahb_bus, HHI_GCLK_AO, 2); 1789static MESON_GATE(meson8b_ao_ahb_bus, HHI_GCLK_AO, 2);
1660static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3); 1790static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3);
1661 1791
1792static struct clk_hw_onecell_data meson8_hw_onecell_data = {
1793 .hws = {
1794 [CLKID_XTAL] = &meson8b_xtal.hw,
1795 [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
1796 [CLKID_PLL_VID] = &meson8b_vid_pll.hw,
1797 [CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
1798 [CLKID_FCLK_DIV2] = &meson8b_fclk_div2.hw,
1799 [CLKID_FCLK_DIV3] = &meson8b_fclk_div3.hw,
1800 [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw,
1801 [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw,
1802 [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw,
1803 [CLKID_CPUCLK] = &meson8b_cpu_clk.hw,
1804 [CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
1805 [CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
1806 [CLKID_CLK81] = &meson8b_clk81.hw,
1807 [CLKID_DDR] = &meson8b_ddr.hw,
1808 [CLKID_DOS] = &meson8b_dos.hw,
1809 [CLKID_ISA] = &meson8b_isa.hw,
1810 [CLKID_PL301] = &meson8b_pl301.hw,
1811 [CLKID_PERIPHS] = &meson8b_periphs.hw,
1812 [CLKID_SPICC] = &meson8b_spicc.hw,
1813 [CLKID_I2C] = &meson8b_i2c.hw,
1814 [CLKID_SAR_ADC] = &meson8b_sar_adc.hw,
1815 [CLKID_SMART_CARD] = &meson8b_smart_card.hw,
1816 [CLKID_RNG0] = &meson8b_rng0.hw,
1817 [CLKID_UART0] = &meson8b_uart0.hw,
1818 [CLKID_SDHC] = &meson8b_sdhc.hw,
1819 [CLKID_STREAM] = &meson8b_stream.hw,
1820 [CLKID_ASYNC_FIFO] = &meson8b_async_fifo.hw,
1821 [CLKID_SDIO] = &meson8b_sdio.hw,
1822 [CLKID_ABUF] = &meson8b_abuf.hw,
1823 [CLKID_HIU_IFACE] = &meson8b_hiu_iface.hw,
1824 [CLKID_ASSIST_MISC] = &meson8b_assist_misc.hw,
1825 [CLKID_SPI] = &meson8b_spi.hw,
1826 [CLKID_I2S_SPDIF] = &meson8b_i2s_spdif.hw,
1827 [CLKID_ETH] = &meson8b_eth.hw,
1828 [CLKID_DEMUX] = &meson8b_demux.hw,
1829 [CLKID_AIU_GLUE] = &meson8b_aiu_glue.hw,
1830 [CLKID_IEC958] = &meson8b_iec958.hw,
1831 [CLKID_I2S_OUT] = &meson8b_i2s_out.hw,
1832 [CLKID_AMCLK] = &meson8b_amclk.hw,
1833 [CLKID_AIFIFO2] = &meson8b_aififo2.hw,
1834 [CLKID_MIXER] = &meson8b_mixer.hw,
1835 [CLKID_MIXER_IFACE] = &meson8b_mixer_iface.hw,
1836 [CLKID_ADC] = &meson8b_adc.hw,
1837 [CLKID_BLKMV] = &meson8b_blkmv.hw,
1838 [CLKID_AIU] = &meson8b_aiu.hw,
1839 [CLKID_UART1] = &meson8b_uart1.hw,
1840 [CLKID_G2D] = &meson8b_g2d.hw,
1841 [CLKID_USB0] = &meson8b_usb0.hw,
1842 [CLKID_USB1] = &meson8b_usb1.hw,
1843 [CLKID_RESET] = &meson8b_reset.hw,
1844 [CLKID_NAND] = &meson8b_nand.hw,
1845 [CLKID_DOS_PARSER] = &meson8b_dos_parser.hw,
1846 [CLKID_USB] = &meson8b_usb.hw,
1847 [CLKID_VDIN1] = &meson8b_vdin1.hw,
1848 [CLKID_AHB_ARB0] = &meson8b_ahb_arb0.hw,
1849 [CLKID_EFUSE] = &meson8b_efuse.hw,
1850 [CLKID_BOOT_ROM] = &meson8b_boot_rom.hw,
1851 [CLKID_AHB_DATA_BUS] = &meson8b_ahb_data_bus.hw,
1852 [CLKID_AHB_CTRL_BUS] = &meson8b_ahb_ctrl_bus.hw,
1853 [CLKID_HDMI_INTR_SYNC] = &meson8b_hdmi_intr_sync.hw,
1854 [CLKID_HDMI_PCLK] = &meson8b_hdmi_pclk.hw,
1855 [CLKID_USB1_DDR_BRIDGE] = &meson8b_usb1_ddr_bridge.hw,
1856 [CLKID_USB0_DDR_BRIDGE] = &meson8b_usb0_ddr_bridge.hw,
1857 [CLKID_MMC_PCLK] = &meson8b_mmc_pclk.hw,
1858 [CLKID_DVIN] = &meson8b_dvin.hw,
1859 [CLKID_UART2] = &meson8b_uart2.hw,
1860 [CLKID_SANA] = &meson8b_sana.hw,
1861 [CLKID_VPU_INTR] = &meson8b_vpu_intr.hw,
1862 [CLKID_SEC_AHB_AHB3_BRIDGE] = &meson8b_sec_ahb_ahb3_bridge.hw,
1863 [CLKID_CLK81_A9] = &meson8b_clk81_a9.hw,
1864 [CLKID_VCLK2_VENCI0] = &meson8b_vclk2_venci0.hw,
1865 [CLKID_VCLK2_VENCI1] = &meson8b_vclk2_venci1.hw,
1866 [CLKID_VCLK2_VENCP0] = &meson8b_vclk2_vencp0.hw,
1867 [CLKID_VCLK2_VENCP1] = &meson8b_vclk2_vencp1.hw,
1868 [CLKID_GCLK_VENCI_INT] = &meson8b_gclk_venci_int.hw,
1869 [CLKID_GCLK_VENCP_INT] = &meson8b_gclk_vencp_int.hw,
1870 [CLKID_DAC_CLK] = &meson8b_dac_clk.hw,
1871 [CLKID_AOCLK_GATE] = &meson8b_aoclk_gate.hw,
1872 [CLKID_IEC958_GATE] = &meson8b_iec958_gate.hw,
1873 [CLKID_ENC480P] = &meson8b_enc480p.hw,
1874 [CLKID_RNG1] = &meson8b_rng1.hw,
1875 [CLKID_GCLK_VENCL_INT] = &meson8b_gclk_vencl_int.hw,
1876 [CLKID_VCLK2_VENCLMCC] = &meson8b_vclk2_venclmcc.hw,
1877 [CLKID_VCLK2_VENCL] = &meson8b_vclk2_vencl.hw,
1878 [CLKID_VCLK2_OTHER] = &meson8b_vclk2_other.hw,
1879 [CLKID_EDP] = &meson8b_edp.hw,
1880 [CLKID_AO_MEDIA_CPU] = &meson8b_ao_media_cpu.hw,
1881 [CLKID_AO_AHB_SRAM] = &meson8b_ao_ahb_sram.hw,
1882 [CLKID_AO_AHB_BUS] = &meson8b_ao_ahb_bus.hw,
1883 [CLKID_AO_IFACE] = &meson8b_ao_iface.hw,
1884 [CLKID_MPLL0] = &meson8b_mpll0.hw,
1885 [CLKID_MPLL1] = &meson8b_mpll1.hw,
1886 [CLKID_MPLL2] = &meson8b_mpll2.hw,
1887 [CLKID_MPLL0_DIV] = &meson8b_mpll0_div.hw,
1888 [CLKID_MPLL1_DIV] = &meson8b_mpll1_div.hw,
1889 [CLKID_MPLL2_DIV] = &meson8b_mpll2_div.hw,
1890 [CLKID_CPU_IN_SEL] = &meson8b_cpu_in_sel.hw,
1891 [CLKID_CPU_IN_DIV2] = &meson8b_cpu_in_div2.hw,
1892 [CLKID_CPU_IN_DIV3] = &meson8b_cpu_in_div3.hw,
1893 [CLKID_CPU_SCALE_DIV] = &meson8b_cpu_scale_div.hw,
1894 [CLKID_CPU_SCALE_OUT_SEL] = &meson8b_cpu_scale_out_sel.hw,
1895 [CLKID_MPLL_PREDIV] = &meson8b_mpll_prediv.hw,
1896 [CLKID_FCLK_DIV2_DIV] = &meson8b_fclk_div2_div.hw,
1897 [CLKID_FCLK_DIV3_DIV] = &meson8b_fclk_div3_div.hw,
1898 [CLKID_FCLK_DIV4_DIV] = &meson8b_fclk_div4_div.hw,
1899 [CLKID_FCLK_DIV5_DIV] = &meson8b_fclk_div5_div.hw,
1900 [CLKID_FCLK_DIV7_DIV] = &meson8b_fclk_div7_div.hw,
1901 [CLKID_NAND_SEL] = &meson8b_nand_clk_sel.hw,
1902 [CLKID_NAND_DIV] = &meson8b_nand_clk_div.hw,
1903 [CLKID_NAND_CLK] = &meson8b_nand_clk_gate.hw,
1904 [CLKID_PLL_FIXED_DCO] = &meson8b_fixed_pll_dco.hw,
1905 [CLKID_HDMI_PLL_DCO] = &meson8b_hdmi_pll_dco.hw,
1906 [CLKID_PLL_SYS_DCO] = &meson8b_sys_pll_dco.hw,
1907 [CLKID_CPU_CLK_DIV2] = &meson8b_cpu_clk_div2.hw,
1908 [CLKID_CPU_CLK_DIV3] = &meson8b_cpu_clk_div3.hw,
1909 [CLKID_CPU_CLK_DIV4] = &meson8b_cpu_clk_div4.hw,
1910 [CLKID_CPU_CLK_DIV5] = &meson8b_cpu_clk_div5.hw,
1911 [CLKID_CPU_CLK_DIV6] = &meson8b_cpu_clk_div6.hw,
1912 [CLKID_CPU_CLK_DIV7] = &meson8b_cpu_clk_div7.hw,
1913 [CLKID_CPU_CLK_DIV8] = &meson8b_cpu_clk_div8.hw,
1914 [CLKID_APB_SEL] = &meson8b_apb_clk_sel.hw,
1915 [CLKID_APB] = &meson8b_apb_clk_gate.hw,
1916 [CLKID_PERIPH_SEL] = &meson8b_periph_clk_sel.hw,
1917 [CLKID_PERIPH] = &meson8b_periph_clk_gate.hw,
1918 [CLKID_AXI_SEL] = &meson8b_axi_clk_sel.hw,
1919 [CLKID_AXI] = &meson8b_axi_clk_gate.hw,
1920 [CLKID_L2_DRAM_SEL] = &meson8b_l2_dram_clk_sel.hw,
1921 [CLKID_L2_DRAM] = &meson8b_l2_dram_clk_gate.hw,
1922 [CLKID_HDMI_PLL_LVDS_OUT] = &meson8b_hdmi_pll_lvds_out.hw,
1923 [CLKID_HDMI_PLL_HDMI_OUT] = &meson8b_hdmi_pll_hdmi_out.hw,
1924 [CLKID_VID_PLL_IN_SEL] = &meson8b_vid_pll_in_sel.hw,
1925 [CLKID_VID_PLL_IN_EN] = &meson8b_vid_pll_in_en.hw,
1926 [CLKID_VID_PLL_PRE_DIV] = &meson8b_vid_pll_pre_div.hw,
1927 [CLKID_VID_PLL_POST_DIV] = &meson8b_vid_pll_post_div.hw,
1928 [CLKID_VID_PLL_FINAL_DIV] = &meson8b_vid_pll_final_div.hw,
1929 [CLKID_VCLK_IN_SEL] = &meson8b_vclk_in_sel.hw,
1930 [CLKID_VCLK_IN_EN] = &meson8b_vclk_in_en.hw,
1931 [CLKID_VCLK_DIV1] = &meson8b_vclk_div1_gate.hw,
1932 [CLKID_VCLK_DIV2_DIV] = &meson8b_vclk_div2_div.hw,
1933 [CLKID_VCLK_DIV2] = &meson8b_vclk_div2_div_gate.hw,
1934 [CLKID_VCLK_DIV4_DIV] = &meson8b_vclk_div4_div.hw,
1935 [CLKID_VCLK_DIV4] = &meson8b_vclk_div4_div_gate.hw,
1936 [CLKID_VCLK_DIV6_DIV] = &meson8b_vclk_div6_div.hw,
1937 [CLKID_VCLK_DIV6] = &meson8b_vclk_div6_div_gate.hw,
1938 [CLKID_VCLK_DIV12_DIV] = &meson8b_vclk_div12_div.hw,
1939 [CLKID_VCLK_DIV12] = &meson8b_vclk_div12_div_gate.hw,
1940 [CLKID_VCLK2_IN_SEL] = &meson8b_vclk2_in_sel.hw,
1941 [CLKID_VCLK2_IN_EN] = &meson8b_vclk2_clk_in_en.hw,
1942 [CLKID_VCLK2_DIV1] = &meson8b_vclk2_div1_gate.hw,
1943 [CLKID_VCLK2_DIV2_DIV] = &meson8b_vclk2_div2_div.hw,
1944 [CLKID_VCLK2_DIV2] = &meson8b_vclk2_div2_div_gate.hw,
1945 [CLKID_VCLK2_DIV4_DIV] = &meson8b_vclk2_div4_div.hw,
1946 [CLKID_VCLK2_DIV4] = &meson8b_vclk2_div4_div_gate.hw,
1947 [CLKID_VCLK2_DIV6_DIV] = &meson8b_vclk2_div6_div.hw,
1948 [CLKID_VCLK2_DIV6] = &meson8b_vclk2_div6_div_gate.hw,
1949 [CLKID_VCLK2_DIV12_DIV] = &meson8b_vclk2_div12_div.hw,
1950 [CLKID_VCLK2_DIV12] = &meson8b_vclk2_div12_div_gate.hw,
1951 [CLKID_CTS_ENCT_SEL] = &meson8b_cts_enct_sel.hw,
1952 [CLKID_CTS_ENCT] = &meson8b_cts_enct.hw,
1953 [CLKID_CTS_ENCP_SEL] = &meson8b_cts_encp_sel.hw,
1954 [CLKID_CTS_ENCP] = &meson8b_cts_encp.hw,
1955 [CLKID_CTS_ENCI_SEL] = &meson8b_cts_enci_sel.hw,
1956 [CLKID_CTS_ENCI] = &meson8b_cts_enci.hw,
1957 [CLKID_HDMI_TX_PIXEL_SEL] = &meson8b_hdmi_tx_pixel_sel.hw,
1958 [CLKID_HDMI_TX_PIXEL] = &meson8b_hdmi_tx_pixel.hw,
1959 [CLKID_CTS_ENCL_SEL] = &meson8b_cts_encl_sel.hw,
1960 [CLKID_CTS_ENCL] = &meson8b_cts_encl.hw,
1961 [CLKID_CTS_VDAC0_SEL] = &meson8b_cts_vdac0_sel.hw,
1962 [CLKID_CTS_VDAC0] = &meson8b_cts_vdac0.hw,
1963 [CLKID_HDMI_SYS_SEL] = &meson8b_hdmi_sys_sel.hw,
1964 [CLKID_HDMI_SYS_DIV] = &meson8b_hdmi_sys_div.hw,
1965 [CLKID_HDMI_SYS] = &meson8b_hdmi_sys.hw,
1966 [CLKID_MALI_0_SEL] = &meson8b_mali_0_sel.hw,
1967 [CLKID_MALI_0_DIV] = &meson8b_mali_0_div.hw,
1968 [CLKID_MALI] = &meson8b_mali_0.hw,
1969 [CLK_NR_CLKS] = NULL,
1970 },
1971 .num = CLK_NR_CLKS,
1972};
1973
1662static struct clk_hw_onecell_data meson8b_hw_onecell_data = { 1974static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
1663 .hws = { 1975 .hws = {
1664 [CLKID_XTAL] = &meson8b_xtal.hw, 1976 [CLKID_XTAL] = &meson8b_xtal.hw,
@@ -1781,8 +2093,8 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
1781 [CLKID_CPU_CLK_DIV6] = &meson8b_cpu_clk_div6.hw, 2093 [CLKID_CPU_CLK_DIV6] = &meson8b_cpu_clk_div6.hw,
1782 [CLKID_CPU_CLK_DIV7] = &meson8b_cpu_clk_div7.hw, 2094 [CLKID_CPU_CLK_DIV7] = &meson8b_cpu_clk_div7.hw,
1783 [CLKID_CPU_CLK_DIV8] = &meson8b_cpu_clk_div8.hw, 2095 [CLKID_CPU_CLK_DIV8] = &meson8b_cpu_clk_div8.hw,
1784 [CLKID_ABP_SEL] = &meson8b_abp_clk_sel.hw, 2096 [CLKID_APB_SEL] = &meson8b_apb_clk_sel.hw,
1785 [CLKID_ABP] = &meson8b_abp_clk_gate.hw, 2097 [CLKID_APB] = &meson8b_apb_clk_gate.hw,
1786 [CLKID_PERIPH_SEL] = &meson8b_periph_clk_sel.hw, 2098 [CLKID_PERIPH_SEL] = &meson8b_periph_clk_sel.hw,
1787 [CLKID_PERIPH] = &meson8b_periph_clk_gate.hw, 2099 [CLKID_PERIPH] = &meson8b_periph_clk_gate.hw,
1788 [CLKID_AXI_SEL] = &meson8b_axi_clk_sel.hw, 2100 [CLKID_AXI_SEL] = &meson8b_axi_clk_sel.hw,
@@ -1833,6 +2145,13 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
1833 [CLKID_HDMI_SYS_SEL] = &meson8b_hdmi_sys_sel.hw, 2145 [CLKID_HDMI_SYS_SEL] = &meson8b_hdmi_sys_sel.hw,
1834 [CLKID_HDMI_SYS_DIV] = &meson8b_hdmi_sys_div.hw, 2146 [CLKID_HDMI_SYS_DIV] = &meson8b_hdmi_sys_div.hw,
1835 [CLKID_HDMI_SYS] = &meson8b_hdmi_sys.hw, 2147 [CLKID_HDMI_SYS] = &meson8b_hdmi_sys.hw,
2148 [CLKID_MALI_0_SEL] = &meson8b_mali_0_sel.hw,
2149 [CLKID_MALI_0_DIV] = &meson8b_mali_0_div.hw,
2150 [CLKID_MALI_0] = &meson8b_mali_0.hw,
2151 [CLKID_MALI_1_SEL] = &meson8b_mali_1_sel.hw,
2152 [CLKID_MALI_1_DIV] = &meson8b_mali_1_div.hw,
2153 [CLKID_MALI_1] = &meson8b_mali_1.hw,
2154 [CLKID_MALI] = &meson8b_mali.hw,
1836 [CLK_NR_CLKS] = NULL, 2155 [CLK_NR_CLKS] = NULL,
1837 }, 2156 },
1838 .num = CLK_NR_CLKS, 2157 .num = CLK_NR_CLKS,
@@ -1943,8 +2262,8 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
1943 &meson8b_fixed_pll_dco, 2262 &meson8b_fixed_pll_dco,
1944 &meson8b_hdmi_pll_dco, 2263 &meson8b_hdmi_pll_dco,
1945 &meson8b_sys_pll_dco, 2264 &meson8b_sys_pll_dco,
1946 &meson8b_abp_clk_sel, 2265 &meson8b_apb_clk_sel,
1947 &meson8b_abp_clk_gate, 2266 &meson8b_apb_clk_gate,
1948 &meson8b_periph_clk_sel, 2267 &meson8b_periph_clk_sel,
1949 &meson8b_periph_clk_gate, 2268 &meson8b_periph_clk_gate,
1950 &meson8b_axi_clk_sel, 2269 &meson8b_axi_clk_sel,
@@ -1988,6 +2307,13 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
1988 &meson8b_hdmi_sys_sel, 2307 &meson8b_hdmi_sys_sel,
1989 &meson8b_hdmi_sys_div, 2308 &meson8b_hdmi_sys_div,
1990 &meson8b_hdmi_sys, 2309 &meson8b_hdmi_sys,
2310 &meson8b_mali_0_sel,
2311 &meson8b_mali_0_div,
2312 &meson8b_mali_0,
2313 &meson8b_mali_1_sel,
2314 &meson8b_mali_1_div,
2315 &meson8b_mali_1,
2316 &meson8b_mali,
1991}; 2317};
1992 2318
1993static const struct meson8b_clk_reset_line { 2319static const struct meson8b_clk_reset_line {
@@ -2132,7 +2458,6 @@ static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
2132 2458
2133static struct meson8b_nb_data meson8b_cpu_nb_data = { 2459static struct meson8b_nb_data meson8b_cpu_nb_data = {
2134 .nb.notifier_call = meson8b_cpu_clk_notifier_cb, 2460 .nb.notifier_call = meson8b_cpu_clk_notifier_cb,
2135 .onecell_data = &meson8b_hw_onecell_data,
2136}; 2461};
2137 2462
2138static const struct regmap_config clkc_regmap_config = { 2463static const struct regmap_config clkc_regmap_config = {
@@ -2141,7 +2466,8 @@ static const struct regmap_config clkc_regmap_config = {
2141 .reg_stride = 4, 2466 .reg_stride = 4,
2142}; 2467};
2143 2468
2144static void __init meson8b_clkc_init(struct device_node *np) 2469static void __init meson8b_clkc_init_common(struct device_node *np,
2470 struct clk_hw_onecell_data *clk_hw_onecell_data)
2145{ 2471{
2146 struct meson8b_clk_reset *rstc; 2472 struct meson8b_clk_reset *rstc;
2147 const char *notifier_clk_name; 2473 const char *notifier_clk_name;
@@ -2192,14 +2518,16 @@ static void __init meson8b_clkc_init(struct device_node *np)
2192 */ 2518 */
2193 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) { 2519 for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
2194 /* array might be sparse */ 2520 /* array might be sparse */
2195 if (!meson8b_hw_onecell_data.hws[i]) 2521 if (!clk_hw_onecell_data->hws[i])
2196 continue; 2522 continue;
2197 2523
2198 ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]); 2524 ret = clk_hw_register(NULL, clk_hw_onecell_data->hws[i]);
2199 if (ret) 2525 if (ret)
2200 return; 2526 return;
2201 } 2527 }
2202 2528
2529 meson8b_cpu_nb_data.onecell_data = clk_hw_onecell_data;
2530
2203 /* 2531 /*
2204 * FIXME we shouldn't program the muxes in notifier handlers. The 2532 * FIXME we shouldn't program the muxes in notifier handlers. The
2205 * tricky programming sequence will be handled by the forthcoming 2533 * tricky programming sequence will be handled by the forthcoming
@@ -2215,13 +2543,23 @@ static void __init meson8b_clkc_init(struct device_node *np)
2215 } 2543 }
2216 2544
2217 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, 2545 ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
2218 &meson8b_hw_onecell_data); 2546 clk_hw_onecell_data);
2219 if (ret) 2547 if (ret)
2220 pr_err("%s: failed to register clock provider\n", __func__); 2548 pr_err("%s: failed to register clock provider\n", __func__);
2221} 2549}
2222 2550
2551static void __init meson8_clkc_init(struct device_node *np)
2552{
2553 return meson8b_clkc_init_common(np, &meson8_hw_onecell_data);
2554}
2555
2556static void __init meson8b_clkc_init(struct device_node *np)
2557{
2558 return meson8b_clkc_init_common(np, &meson8b_hw_onecell_data);
2559}
2560
2223CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc", 2561CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
2224 meson8b_clkc_init); 2562 meson8_clkc_init);
2225CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc", 2563CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
2226 meson8b_clkc_init); 2564 meson8b_clkc_init);
2227CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc", 2565CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
diff --git a/drivers/clk/meson/meson8b.h b/drivers/clk/meson/meson8b.h
index 87fba739af81..b8c58faeae52 100644
--- a/drivers/clk/meson/meson8b.h
+++ b/drivers/clk/meson/meson8b.h
@@ -33,6 +33,7 @@
33#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */ 33#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
34#define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */ 34#define HHI_VID_DIVIDER_CNTL 0x198 /* 0x66 offset in data sheet */
35#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */ 35#define HHI_SYS_CPU_CLK_CNTL0 0x19c /* 0x67 offset in data sheet */
36#define HHI_MALI_CLK_CNTL 0x1b0 /* 0x6c offset in data sheet */
36#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */ 37#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
37#define HHI_NAND_CLK_CNTL 0x25c /* 0x97 offset in data sheet */ 38#define HHI_NAND_CLK_CNTL 0x25c /* 0x97 offset in data sheet */
38#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */ 39#define HHI_MPLL_CNTL 0x280 /* 0xa0 offset in data sheet */
@@ -91,7 +92,7 @@
91#define CLKID_CPU_CLK_DIV6 120 92#define CLKID_CPU_CLK_DIV6 120
92#define CLKID_CPU_CLK_DIV7 121 93#define CLKID_CPU_CLK_DIV7 121
93#define CLKID_CPU_CLK_DIV8 122 94#define CLKID_CPU_CLK_DIV8 122
94#define CLKID_ABP_SEL 123 95#define CLKID_APB_SEL 123
95#define CLKID_PERIPH_SEL 125 96#define CLKID_PERIPH_SEL 125
96#define CLKID_AXI_SEL 127 97#define CLKID_AXI_SEL 127
97#define CLKID_L2_DRAM_SEL 129 98#define CLKID_L2_DRAM_SEL 129
@@ -139,8 +140,14 @@
139#define CLKID_HDMI_SYS_SEL 172 140#define CLKID_HDMI_SYS_SEL 172
140#define CLKID_HDMI_SYS_DIV 173 141#define CLKID_HDMI_SYS_DIV 173
141#define CLKID_HDMI_SYS 174 142#define CLKID_HDMI_SYS 174
143#define CLKID_MALI_0_SEL 175
144#define CLKID_MALI_0_DIV 176
145#define CLKID_MALI_0 177
146#define CLKID_MALI_1_SEL 178
147#define CLKID_MALI_1_DIV 179
148#define CLKID_MALI_1 180
142 149
143#define CLK_NR_CLKS 175 150#define CLK_NR_CLKS 181
144 151
145/* 152/*
146 * include the CLKID and RESETID that have 153 * include the CLKID and RESETID that have
diff --git a/drivers/clk/meson/parm.h b/drivers/clk/meson/parm.h
new file mode 100644
index 000000000000..3c9ef1b505ce
--- /dev/null
+++ b/drivers/clk/meson/parm.h
@@ -0,0 +1,46 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2015 Endless Mobile, Inc.
4 * Author: Carlo Caione <carlo@endlessm.com>
5 */
6
7#ifndef __MESON_PARM_H
8#define __MESON_PARM_H
9
10#include <linux/bits.h>
11#include <linux/regmap.h>
12
13#define PMASK(width) GENMASK(width - 1, 0)
14#define SETPMASK(width, shift) GENMASK(shift + width - 1, shift)
15#define CLRPMASK(width, shift) (~SETPMASK(width, shift))
16
17#define PARM_GET(width, shift, reg) \
18 (((reg) & SETPMASK(width, shift)) >> (shift))
19#define PARM_SET(width, shift, reg, val) \
20 (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
21
22#define MESON_PARM_APPLICABLE(p) (!!((p)->width))
23
24struct parm {
25 u16 reg_off;
26 u8 shift;
27 u8 width;
28};
29
30static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
31{
32 unsigned int val;
33
34 regmap_read(map, p->reg_off, &val);
35 return PARM_GET(p->width, p->shift, val);
36}
37
38static inline void meson_parm_write(struct regmap *map, struct parm *p,
39 unsigned int val)
40{
41 regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
42 val << p->shift);
43}
44
45#endif /* __MESON_PARM_H */
46
diff --git a/drivers/clk/meson/sclk-div.c b/drivers/clk/meson/sclk-div.c
index bc64019b8eeb..3acf03780221 100644
--- a/drivers/clk/meson/sclk-div.c
+++ b/drivers/clk/meson/sclk-div.c
@@ -16,7 +16,11 @@
16 * duty_cycle = (1 + hi) / (1 + val) 16 * duty_cycle = (1 + hi) / (1 + val)
17 */ 17 */
18 18
19#include "clkc-audio.h" 19#include <linux/clk-provider.h>
20#include <linux/module.h>
21
22#include "clk-regmap.h"
23#include "sclk-div.h"
20 24
21static inline struct meson_sclk_div_data * 25static inline struct meson_sclk_div_data *
22meson_sclk_div_data(struct clk_regmap *clk) 26meson_sclk_div_data(struct clk_regmap *clk)
@@ -241,3 +245,7 @@ const struct clk_ops meson_sclk_div_ops = {
241 .init = sclk_div_init, 245 .init = sclk_div_init,
242}; 246};
243EXPORT_SYMBOL_GPL(meson_sclk_div_ops); 247EXPORT_SYMBOL_GPL(meson_sclk_div_ops);
248
249MODULE_DESCRIPTION("Amlogic Sample divider driver");
250MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
251MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clkc-audio.h b/drivers/clk/meson/sclk-div.h
index 0a7c157ebf81..b64b2a32005f 100644
--- a/drivers/clk/meson/clkc-audio.h
+++ b/drivers/clk/meson/sclk-div.h
@@ -4,16 +4,11 @@
4 * Author: Jerome Brunet <jbrunet@baylibre.com> 4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */ 5 */
6 6
7#ifndef __MESON_CLKC_AUDIO_H 7#ifndef __MESON_SCLK_DIV_H
8#define __MESON_CLKC_AUDIO_H 8#define __MESON_SCLK_DIV_H
9 9
10#include "clkc.h" 10#include <linux/clk-provider.h>
11 11#include "parm.h"
12struct meson_clk_triphase_data {
13 struct parm ph0;
14 struct parm ph1;
15 struct parm ph2;
16};
17 12
18struct meson_sclk_div_data { 13struct meson_sclk_div_data {
19 struct parm div; 14 struct parm div;
@@ -22,7 +17,6 @@ struct meson_sclk_div_data {
22 struct clk_duty cached_duty; 17 struct clk_duty cached_duty;
23}; 18};
24 19
25extern const struct clk_ops meson_clk_triphase_ops;
26extern const struct clk_ops meson_sclk_div_ops; 20extern const struct clk_ops meson_sclk_div_ops;
27 21
28#endif /* __MESON_CLKC_AUDIO_H */ 22#endif /* __MESON_SCLK_DIV_H */
diff --git a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c
index 88af0e282ea0..08bcc01c0923 100644
--- a/drivers/clk/meson/vid-pll-div.c
+++ b/drivers/clk/meson/vid-pll-div.c
@@ -5,7 +5,10 @@
5 */ 5 */
6 6
7#include <linux/clk-provider.h> 7#include <linux/clk-provider.h>
8#include "clkc.h" 8#include <linux/module.h>
9
10#include "clk-regmap.h"
11#include "vid-pll-div.h"
9 12
10static inline struct meson_vid_pll_div_data * 13static inline struct meson_vid_pll_div_data *
11meson_vid_pll_div_data(struct clk_regmap *clk) 14meson_vid_pll_div_data(struct clk_regmap *clk)
@@ -89,3 +92,8 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
89const struct clk_ops meson_vid_pll_div_ro_ops = { 92const struct clk_ops meson_vid_pll_div_ro_ops = {
90 .recalc_rate = meson_vid_pll_div_recalc_rate, 93 .recalc_rate = meson_vid_pll_div_recalc_rate,
91}; 94};
95EXPORT_SYMBOL_GPL(meson_vid_pll_div_ro_ops);
96
97MODULE_DESCRIPTION("Amlogic video pll divider driver");
98MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
99MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/vid-pll-div.h b/drivers/clk/meson/vid-pll-div.h
new file mode 100644
index 000000000000..c0128e33ccf9
--- /dev/null
+++ b/drivers/clk/meson/vid-pll-div.h
@@ -0,0 +1,20 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Copyright (c) 2019 BayLibre, SAS.
4 * Author: Jerome Brunet <jbrunet@baylibre.com>
5 */
6
7#ifndef __MESON_VID_PLL_DIV_H
8#define __MESON_VID_PLL_DIV_H
9
10#include <linux/clk-provider.h>
11#include "parm.h"
12
13struct meson_vid_pll_div_data {
14 struct parm val;
15 struct parm sel;
16};
17
18extern const struct clk_ops meson_vid_pll_div_ro_ops;
19
20#endif /* __MESON_VID_PLL_DIV_H */