xref: /linux/drivers/clk/meson/a9-aoclk.c (revision 502d45774af09f1c681c754c4b7cdfb5d7f72fd9)
1*a1b4c3a6SJian Hu // SPDX-License-Identifier: (GPL-2.0-only OR MIT)
2*a1b4c3a6SJian Hu /*
3*a1b4c3a6SJian Hu  * Copyright (C) 2026 Amlogic, Inc. All rights reserved
4*a1b4c3a6SJian Hu  */
5*a1b4c3a6SJian Hu 
6*a1b4c3a6SJian Hu #include <dt-bindings/clock/amlogic,a9-aoclkc.h>
7*a1b4c3a6SJian Hu #include <linux/clk-provider.h>
8*a1b4c3a6SJian Hu #include <linux/module.h>
9*a1b4c3a6SJian Hu #include <linux/platform_device.h>
10*a1b4c3a6SJian Hu #include "clk-regmap.h"
11*a1b4c3a6SJian Hu #include "clk-dualdiv.h"
12*a1b4c3a6SJian Hu #include "meson-clkc-utils.h"
13*a1b4c3a6SJian Hu 
14*a1b4c3a6SJian Hu #define AO_OSCIN_CTRL			0x00
15*a1b4c3a6SJian Hu #define AO_SYS_CLK0			0x04
16*a1b4c3a6SJian Hu #define AO_PWM_CLK_A_CTRL		0x1c
17*a1b4c3a6SJian Hu #define AO_PWM_CLK_B_CTRL		0x20
18*a1b4c3a6SJian Hu #define AO_PWM_CLK_C_CTRL		0x24
19*a1b4c3a6SJian Hu #define AO_PWM_CLK_D_CTRL		0x28
20*a1b4c3a6SJian Hu #define AO_PWM_CLK_E_CTRL		0x2c
21*a1b4c3a6SJian Hu #define AO_PWM_CLK_F_CTRL		0x30
22*a1b4c3a6SJian Hu #define AO_PWM_CLK_G_CTRL		0x34
23*a1b4c3a6SJian Hu #define AO_CEC_CTRL0			0x38
24*a1b4c3a6SJian Hu #define AO_CEC_CTRL1			0x3c
25*a1b4c3a6SJian Hu #define AO_RTC_BY_OSCIN_CTRL0		0x50
26*a1b4c3a6SJian Hu #define AO_RTC_BY_OSCIN_CTRL1		0x54
27*a1b4c3a6SJian Hu 
28*a1b4c3a6SJian Hu #define A9_COMP_SEL(_name, _reg, _shift, _mask, _pdata) \
29*a1b4c3a6SJian Hu 	MESON_COMP_SEL(a9_ao_, _name, _reg, _shift, _mask, _pdata, NULL, 0, 0)
30*a1b4c3a6SJian Hu 
31*a1b4c3a6SJian Hu #define A9_COMP_DIV(_name, _reg, _shift, _width) \
32*a1b4c3a6SJian Hu 	MESON_COMP_DIV(a9_ao_, _name, _reg, _shift, _width, 0, CLK_SET_RATE_PARENT)
33*a1b4c3a6SJian Hu 
34*a1b4c3a6SJian Hu #define A9_COMP_GATE(_name, _reg, _bit) \
35*a1b4c3a6SJian Hu 	MESON_COMP_GATE(a9_ao_, _name, _reg, _bit, CLK_SET_RATE_PARENT)
36*a1b4c3a6SJian Hu 
37*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_xtal_in = {
38*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_gate_data){
39*a1b4c3a6SJian Hu 		.offset = AO_OSCIN_CTRL,
40*a1b4c3a6SJian Hu 		.bit_idx = 3,
41*a1b4c3a6SJian Hu 	},
42*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data) {
43*a1b4c3a6SJian Hu 		.name = "ao_xtal_in",
44*a1b4c3a6SJian Hu 		.ops = &clk_regmap_gate_ops,
45*a1b4c3a6SJian Hu 		.parent_data = &(const struct clk_parent_data) {
46*a1b4c3a6SJian Hu 			.fw_name = "xtal",
47*a1b4c3a6SJian Hu 		},
48*a1b4c3a6SJian Hu 		.num_parents = 1,
49*a1b4c3a6SJian Hu 	},
50*a1b4c3a6SJian Hu };
51*a1b4c3a6SJian Hu 
52*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_xtal = {
53*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
54*a1b4c3a6SJian Hu 		.offset = AO_OSCIN_CTRL,
55*a1b4c3a6SJian Hu 		.mask = 0x1,
56*a1b4c3a6SJian Hu 		.shift = 0,
57*a1b4c3a6SJian Hu 	},
58*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
59*a1b4c3a6SJian Hu 		.name = "ao_xtal",
60*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
61*a1b4c3a6SJian Hu 		/* ext_32k is from external PAD, do not automatically reparent */
62*a1b4c3a6SJian Hu 		.parent_data = (const struct clk_parent_data []) {
63*a1b4c3a6SJian Hu 			{ .hw = &a9_ao_xtal_in.hw },
64*a1b4c3a6SJian Hu 			{ .fw_name = "ext_32k", },
65*a1b4c3a6SJian Hu 		},
66*a1b4c3a6SJian Hu 		.num_parents = 2,
67*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_NO_REPARENT,
68*a1b4c3a6SJian Hu 	},
69*a1b4c3a6SJian Hu };
70*a1b4c3a6SJian Hu 
71*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_sys = {
72*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
73*a1b4c3a6SJian Hu 		.offset = AO_OSCIN_CTRL,
74*a1b4c3a6SJian Hu 		.mask = 0x1,
75*a1b4c3a6SJian Hu 		.shift = 1,
76*a1b4c3a6SJian Hu 	},
77*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
78*a1b4c3a6SJian Hu 		.name = "ao_sys",
79*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
80*a1b4c3a6SJian Hu 		.parent_data = (const struct clk_parent_data []) {
81*a1b4c3a6SJian Hu 			{ .hw = &a9_ao_xtal.hw },
82*a1b4c3a6SJian Hu 			{ .fw_name = "sys", },
83*a1b4c3a6SJian Hu 		},
84*a1b4c3a6SJian Hu 		.num_parents = 2,
85*a1b4c3a6SJian Hu 	},
86*a1b4c3a6SJian Hu };
87*a1b4c3a6SJian Hu 
88*a1b4c3a6SJian Hu static const struct clk_parent_data a9_ao_pclk_parents = { .hw = &a9_ao_sys.hw };
89*a1b4c3a6SJian Hu 
90*a1b4c3a6SJian Hu #define A9_AO_PCLK(_name, _bit, _flags)		       \
91*a1b4c3a6SJian Hu 	MESON_PCLK(a9_ao_sys_##_name, AO_SYS_CLK0, _bit, \
92*a1b4c3a6SJian Hu 		   &a9_ao_pclk_parents, _flags)
93*a1b4c3a6SJian Hu 
94*a1b4c3a6SJian Hu /*
95*a1b4c3a6SJian Hu  * A9 integrates a low-power microprocessor (Always-on CPU: AOCPU). Some AO sys
96*a1b4c3a6SJian Hu  * clocks control the AOCPU modules. Mark the AOCPU-related clocks with
97*a1b4c3a6SJian Hu  * CLK_IS_CRITICAL to avoid them being disabled and impacting AOCPU functionality.
98*a1b4c3a6SJian Hu  * AOCPU-related clocks list:
99*a1b4c3a6SJian Hu  * - clktree
100*a1b4c3a6SJian Hu  * - rst_ctrl
101*a1b4c3a6SJian Hu  * - pad
102*a1b4c3a6SJian Hu  * - irq
103*a1b4c3a6SJian Hu  * - pwrctrl
104*a1b4c3a6SJian Hu  * - aocpu
105*a1b4c3a6SJian Hu  * - sram
106*a1b4c3a6SJian Hu  */
107*a1b4c3a6SJian Hu static A9_AO_PCLK(i3c,		0,	0);
108*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_reg,	1,	0);
109*a1b4c3a6SJian Hu static A9_AO_PCLK(clktree,	2,	CLK_IS_CRITICAL);
110*a1b4c3a6SJian Hu static A9_AO_PCLK(rst_ctrl,	3,	CLK_IS_CRITICAL);
111*a1b4c3a6SJian Hu static A9_AO_PCLK(pad,		4,	CLK_IS_CRITICAL);
112*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_dig,	5,	0);
113*a1b4c3a6SJian Hu static A9_AO_PCLK(irq,		6,	CLK_IS_CRITICAL);
114*a1b4c3a6SJian Hu static A9_AO_PCLK(pwrctrl,	7,	CLK_IS_CRITICAL);
115*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_a,	8,	0);
116*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_b,	9,	0);
117*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_c,	10,	0);
118*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_d,	11,	0);
119*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_e,	12,	0);
120*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_f,	13,	0);
121*a1b4c3a6SJian Hu static A9_AO_PCLK(pwm_g,	14,	0);
122*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_a,	15,	0);
123*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_b,	16,	0);
124*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_c,	17,	0);
125*a1b4c3a6SJian Hu static A9_AO_PCLK(i2c_d,	18,	0);
126*a1b4c3a6SJian Hu static A9_AO_PCLK(sed,		19,	0);
127*a1b4c3a6SJian Hu static A9_AO_PCLK(ir_ctrl,	20,	0);
128*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_b,	21,	0);
129*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_c,	22,	0);
130*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_d,	23,	0);
131*a1b4c3a6SJian Hu static A9_AO_PCLK(uart_e,	24,	0);
132*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_0,	25,	0);
133*a1b4c3a6SJian Hu static A9_AO_PCLK(rtc_secure,	26,	0);
134*a1b4c3a6SJian Hu static A9_AO_PCLK(cec,		27,	0);
135*a1b4c3a6SJian Hu static A9_AO_PCLK(aocpu,	28,	CLK_IS_CRITICAL);
136*a1b4c3a6SJian Hu static A9_AO_PCLK(sram,		29,	CLK_IS_CRITICAL);
137*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_1,	30,	0);
138*a1b4c3a6SJian Hu static A9_AO_PCLK(spisg_2,	31,	0);
139*a1b4c3a6SJian Hu 
140*a1b4c3a6SJian Hu static const struct clk_parent_data a9_ao_pwm_parents[] = {
141*a1b4c3a6SJian Hu 	{ .hw = &a9_ao_xtal.hw },
142*a1b4c3a6SJian Hu 	{ .fw_name = "fdiv5", },
143*a1b4c3a6SJian Hu 	{ .fw_name = "fdiv4", },
144*a1b4c3a6SJian Hu 	{ .fw_name = "fdiv3", }
145*a1b4c3a6SJian Hu };
146*a1b4c3a6SJian Hu 
147*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_a, AO_PWM_CLK_A_CTRL, 9, 0x7, a9_ao_pwm_parents);
148*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_a, AO_PWM_CLK_A_CTRL, 0, 8);
149*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_a, AO_PWM_CLK_A_CTRL, 8);
150*a1b4c3a6SJian Hu 
151*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_b, AO_PWM_CLK_B_CTRL, 9, 0x7, a9_ao_pwm_parents);
152*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_b, AO_PWM_CLK_B_CTRL, 0, 8);
153*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_b, AO_PWM_CLK_B_CTRL, 8);
154*a1b4c3a6SJian Hu 
155*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_c, AO_PWM_CLK_C_CTRL, 9, 0x7, a9_ao_pwm_parents);
156*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_c, AO_PWM_CLK_C_CTRL, 0, 8);
157*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_c, AO_PWM_CLK_C_CTRL, 8);
158*a1b4c3a6SJian Hu 
159*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_d, AO_PWM_CLK_D_CTRL, 9, 0x7, a9_ao_pwm_parents);
160*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_d, AO_PWM_CLK_D_CTRL, 0, 8);
161*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_d, AO_PWM_CLK_D_CTRL, 8);
162*a1b4c3a6SJian Hu 
163*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_e, AO_PWM_CLK_E_CTRL, 9, 0x7, a9_ao_pwm_parents);
164*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_e, AO_PWM_CLK_E_CTRL, 0, 8);
165*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_e, AO_PWM_CLK_E_CTRL, 8);
166*a1b4c3a6SJian Hu 
167*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_f, AO_PWM_CLK_F_CTRL, 9, 0x7, a9_ao_pwm_parents);
168*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_f, AO_PWM_CLK_F_CTRL, 0, 8);
169*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_f, AO_PWM_CLK_F_CTRL, 8);
170*a1b4c3a6SJian Hu 
171*a1b4c3a6SJian Hu static A9_COMP_SEL(pwm_g, AO_PWM_CLK_G_CTRL, 9, 0x7, a9_ao_pwm_parents);
172*a1b4c3a6SJian Hu static A9_COMP_DIV(pwm_g, AO_PWM_CLK_G_CTRL, 0, 8);
173*a1b4c3a6SJian Hu static A9_COMP_GATE(pwm_g, AO_PWM_CLK_G_CTRL, 8);
174*a1b4c3a6SJian Hu 
175*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_in = {
176*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_gate_data){
177*a1b4c3a6SJian Hu 		.offset = AO_RTC_BY_OSCIN_CTRL0,
178*a1b4c3a6SJian Hu 		.bit_idx = 31,
179*a1b4c3a6SJian Hu 	},
180*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data) {
181*a1b4c3a6SJian Hu 		.name = "ao_rtc_dualdiv_in",
182*a1b4c3a6SJian Hu 		.ops = &clk_regmap_gate_ops,
183*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
184*a1b4c3a6SJian Hu 			&a9_ao_xtal.hw
185*a1b4c3a6SJian Hu 		},
186*a1b4c3a6SJian Hu 		.num_parents = 1,
187*a1b4c3a6SJian Hu 	},
188*a1b4c3a6SJian Hu };
189*a1b4c3a6SJian Hu 
190*a1b4c3a6SJian Hu static const struct meson_clk_dualdiv_param a9_ao_dualdiv_table[] = {
191*a1b4c3a6SJian Hu 	{ 733, 732, 8, 11, 1 },
192*a1b4c3a6SJian Hu 	{ /* sentinel */ }
193*a1b4c3a6SJian Hu };
194*a1b4c3a6SJian Hu 
195*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_div = {
196*a1b4c3a6SJian Hu 	.data = &(struct meson_clk_dualdiv_data){
197*a1b4c3a6SJian Hu 		.n1 = {
198*a1b4c3a6SJian Hu 			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
199*a1b4c3a6SJian Hu 			.shift   = 0,
200*a1b4c3a6SJian Hu 			.width   = 12,
201*a1b4c3a6SJian Hu 		},
202*a1b4c3a6SJian Hu 		.n2 = {
203*a1b4c3a6SJian Hu 			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
204*a1b4c3a6SJian Hu 			.shift   = 12,
205*a1b4c3a6SJian Hu 			.width   = 12,
206*a1b4c3a6SJian Hu 		},
207*a1b4c3a6SJian Hu 		.m1 = {
208*a1b4c3a6SJian Hu 			.reg_off = AO_RTC_BY_OSCIN_CTRL1,
209*a1b4c3a6SJian Hu 			.shift   = 0,
210*a1b4c3a6SJian Hu 			.width   = 12,
211*a1b4c3a6SJian Hu 		},
212*a1b4c3a6SJian Hu 		.m2 = {
213*a1b4c3a6SJian Hu 			.reg_off = AO_RTC_BY_OSCIN_CTRL1,
214*a1b4c3a6SJian Hu 			.shift   = 12,
215*a1b4c3a6SJian Hu 			.width   = 12,
216*a1b4c3a6SJian Hu 		},
217*a1b4c3a6SJian Hu 		.dual = {
218*a1b4c3a6SJian Hu 			.reg_off = AO_RTC_BY_OSCIN_CTRL0,
219*a1b4c3a6SJian Hu 			.shift   = 28,
220*a1b4c3a6SJian Hu 			.width   = 1,
221*a1b4c3a6SJian Hu 		},
222*a1b4c3a6SJian Hu 		.table = a9_ao_dualdiv_table,
223*a1b4c3a6SJian Hu 	},
224*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
225*a1b4c3a6SJian Hu 		.name = "a9_ao_rtc_dualdiv_div",
226*a1b4c3a6SJian Hu 		.ops = &meson_clk_dualdiv_ops,
227*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
228*a1b4c3a6SJian Hu 			&a9_ao_rtc_dualdiv_in.hw
229*a1b4c3a6SJian Hu 		},
230*a1b4c3a6SJian Hu 		.num_parents = 1,
231*a1b4c3a6SJian Hu 	},
232*a1b4c3a6SJian Hu };
233*a1b4c3a6SJian Hu 
234*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv_sel = {
235*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
236*a1b4c3a6SJian Hu 		.offset = AO_RTC_BY_OSCIN_CTRL1,
237*a1b4c3a6SJian Hu 		.mask = 0x1,
238*a1b4c3a6SJian Hu 		.shift = 24,
239*a1b4c3a6SJian Hu 	},
240*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
241*a1b4c3a6SJian Hu 		.name = "ao_rtc_dualdiv_sel",
242*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
243*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
244*a1b4c3a6SJian Hu 			&a9_ao_rtc_dualdiv_div.hw,
245*a1b4c3a6SJian Hu 			&a9_ao_rtc_dualdiv_in.hw,
246*a1b4c3a6SJian Hu 		},
247*a1b4c3a6SJian Hu 		.num_parents = 2,
248*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
249*a1b4c3a6SJian Hu 	},
250*a1b4c3a6SJian Hu };
251*a1b4c3a6SJian Hu 
252*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc_dualdiv = {
253*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_gate_data){
254*a1b4c3a6SJian Hu 		.offset = AO_RTC_BY_OSCIN_CTRL0,
255*a1b4c3a6SJian Hu 		.bit_idx = 30,
256*a1b4c3a6SJian Hu 	},
257*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data) {
258*a1b4c3a6SJian Hu 		.name = "ao_rtc_dualdiv",
259*a1b4c3a6SJian Hu 		.ops = &clk_regmap_gate_ops,
260*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
261*a1b4c3a6SJian Hu 			&a9_ao_rtc_dualdiv_sel.hw
262*a1b4c3a6SJian Hu 		},
263*a1b4c3a6SJian Hu 		.num_parents = 1,
264*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
265*a1b4c3a6SJian Hu 	},
266*a1b4c3a6SJian Hu };
267*a1b4c3a6SJian Hu 
268*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_rtc = {
269*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
270*a1b4c3a6SJian Hu 		.offset = AO_RTC_BY_OSCIN_CTRL1,
271*a1b4c3a6SJian Hu 		.mask = 0x1,
272*a1b4c3a6SJian Hu 		.shift = 30,
273*a1b4c3a6SJian Hu 	},
274*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
275*a1b4c3a6SJian Hu 		.name = "ao_rtc",
276*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
277*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
278*a1b4c3a6SJian Hu 			&a9_ao_xtal.hw,
279*a1b4c3a6SJian Hu 			&a9_ao_rtc_dualdiv.hw,
280*a1b4c3a6SJian Hu 		},
281*a1b4c3a6SJian Hu 		.num_parents = 2,
282*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
283*a1b4c3a6SJian Hu 	},
284*a1b4c3a6SJian Hu };
285*a1b4c3a6SJian Hu 
286*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_in = {
287*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_gate_data){
288*a1b4c3a6SJian Hu 		.offset = AO_CEC_CTRL0,
289*a1b4c3a6SJian Hu 		.bit_idx = 31,
290*a1b4c3a6SJian Hu 	},
291*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data) {
292*a1b4c3a6SJian Hu 		.name = "ao_cec_dualdiv_in",
293*a1b4c3a6SJian Hu 		.ops = &clk_regmap_gate_ops,
294*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
295*a1b4c3a6SJian Hu 			&a9_ao_xtal.hw
296*a1b4c3a6SJian Hu 		},
297*a1b4c3a6SJian Hu 		.num_parents = 1,
298*a1b4c3a6SJian Hu 	},
299*a1b4c3a6SJian Hu };
300*a1b4c3a6SJian Hu 
301*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_div = {
302*a1b4c3a6SJian Hu 	.data = &(struct meson_clk_dualdiv_data){
303*a1b4c3a6SJian Hu 		.n1 = {
304*a1b4c3a6SJian Hu 			.reg_off = AO_CEC_CTRL0,
305*a1b4c3a6SJian Hu 			.shift   = 0,
306*a1b4c3a6SJian Hu 			.width   = 12,
307*a1b4c3a6SJian Hu 		},
308*a1b4c3a6SJian Hu 		.n2 = {
309*a1b4c3a6SJian Hu 			.reg_off = AO_CEC_CTRL0,
310*a1b4c3a6SJian Hu 			.shift   = 12,
311*a1b4c3a6SJian Hu 			.width   = 12,
312*a1b4c3a6SJian Hu 		},
313*a1b4c3a6SJian Hu 		.m1 = {
314*a1b4c3a6SJian Hu 			.reg_off = AO_CEC_CTRL1,
315*a1b4c3a6SJian Hu 			.shift   = 0,
316*a1b4c3a6SJian Hu 			.width   = 12,
317*a1b4c3a6SJian Hu 		},
318*a1b4c3a6SJian Hu 		.m2 = {
319*a1b4c3a6SJian Hu 			.reg_off = AO_CEC_CTRL1,
320*a1b4c3a6SJian Hu 			.shift   = 12,
321*a1b4c3a6SJian Hu 			.width   = 12,
322*a1b4c3a6SJian Hu 		},
323*a1b4c3a6SJian Hu 		.dual = {
324*a1b4c3a6SJian Hu 			.reg_off = AO_CEC_CTRL0,
325*a1b4c3a6SJian Hu 			.shift   = 28,
326*a1b4c3a6SJian Hu 			.width   = 1,
327*a1b4c3a6SJian Hu 		},
328*a1b4c3a6SJian Hu 		.table = a9_ao_dualdiv_table,
329*a1b4c3a6SJian Hu 	},
330*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
331*a1b4c3a6SJian Hu 		.name = "ao_cec_dualdiv_div",
332*a1b4c3a6SJian Hu 		.ops = &meson_clk_dualdiv_ops,
333*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
334*a1b4c3a6SJian Hu 			&a9_ao_cec_dualdiv_in.hw
335*a1b4c3a6SJian Hu 		},
336*a1b4c3a6SJian Hu 		.num_parents = 1,
337*a1b4c3a6SJian Hu 	},
338*a1b4c3a6SJian Hu };
339*a1b4c3a6SJian Hu 
340*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv_sel = {
341*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
342*a1b4c3a6SJian Hu 		.offset = AO_CEC_CTRL1,
343*a1b4c3a6SJian Hu 		.mask = 0x1,
344*a1b4c3a6SJian Hu 		.shift = 24,
345*a1b4c3a6SJian Hu 	},
346*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
347*a1b4c3a6SJian Hu 		.name = "ao_cec_dualdiv_sel",
348*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
349*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
350*a1b4c3a6SJian Hu 			&a9_ao_cec_dualdiv_div.hw,
351*a1b4c3a6SJian Hu 			&a9_ao_cec_dualdiv_in.hw,
352*a1b4c3a6SJian Hu 		},
353*a1b4c3a6SJian Hu 		.num_parents = 2,
354*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
355*a1b4c3a6SJian Hu 	},
356*a1b4c3a6SJian Hu };
357*a1b4c3a6SJian Hu 
358*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec_dualdiv = {
359*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_gate_data){
360*a1b4c3a6SJian Hu 		.offset = AO_CEC_CTRL0,
361*a1b4c3a6SJian Hu 		.bit_idx = 30,
362*a1b4c3a6SJian Hu 	},
363*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
364*a1b4c3a6SJian Hu 		.name = "ao_cec_dualdiv",
365*a1b4c3a6SJian Hu 		.ops = &clk_regmap_gate_ops,
366*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
367*a1b4c3a6SJian Hu 			&a9_ao_cec_dualdiv_sel.hw
368*a1b4c3a6SJian Hu 		},
369*a1b4c3a6SJian Hu 		.num_parents = 1,
370*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
371*a1b4c3a6SJian Hu 	},
372*a1b4c3a6SJian Hu };
373*a1b4c3a6SJian Hu 
374*a1b4c3a6SJian Hu static struct clk_regmap a9_ao_cec = {
375*a1b4c3a6SJian Hu 	.data = &(struct clk_regmap_mux_data) {
376*a1b4c3a6SJian Hu 		.offset = AO_CEC_CTRL1,
377*a1b4c3a6SJian Hu 		.mask = 0x1,
378*a1b4c3a6SJian Hu 		.shift = 30,
379*a1b4c3a6SJian Hu 	},
380*a1b4c3a6SJian Hu 	.hw.init = &(struct clk_init_data){
381*a1b4c3a6SJian Hu 		.name = "ao_cec",
382*a1b4c3a6SJian Hu 		.ops = &clk_regmap_mux_ops,
383*a1b4c3a6SJian Hu 		.parent_hws = (const struct clk_hw *[]) {
384*a1b4c3a6SJian Hu 			&a9_ao_cec_dualdiv.hw,
385*a1b4c3a6SJian Hu 			&a9_ao_rtc.hw,
386*a1b4c3a6SJian Hu 		},
387*a1b4c3a6SJian Hu 		.num_parents = 2,
388*a1b4c3a6SJian Hu 		.flags = CLK_SET_RATE_PARENT,
389*a1b4c3a6SJian Hu 	},
390*a1b4c3a6SJian Hu };
391*a1b4c3a6SJian Hu 
392*a1b4c3a6SJian Hu static struct clk_hw *a9_ao_hw_clks[] = {
393*a1b4c3a6SJian Hu 	[CLKID_AO_XTAL_IN]		= &a9_ao_xtal_in.hw,
394*a1b4c3a6SJian Hu 	[CLKID_AO_XTAL]			= &a9_ao_xtal.hw,
395*a1b4c3a6SJian Hu 	[CLKID_AO_SYS]			= &a9_ao_sys.hw,
396*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_I3C]		= &a9_ao_sys_i3c.hw,
397*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_RTC_REG]		= &a9_ao_sys_rtc_reg.hw,
398*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_CLKTREE]		= &a9_ao_sys_clktree.hw,
399*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_RST_CTRL]		= &a9_ao_sys_rst_ctrl.hw,
400*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PAD]		= &a9_ao_sys_pad.hw,
401*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_RTC_DIG]		= &a9_ao_sys_rtc_dig.hw,
402*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_IRQ]		= &a9_ao_sys_irq.hw,
403*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWRCTRL]		= &a9_ao_sys_pwrctrl.hw,
404*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_A]		= &a9_ao_sys_pwm_a.hw,
405*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_B]		= &a9_ao_sys_pwm_b.hw,
406*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_C]		= &a9_ao_sys_pwm_c.hw,
407*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_D]		= &a9_ao_sys_pwm_d.hw,
408*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_E]		= &a9_ao_sys_pwm_e.hw,
409*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_F]		= &a9_ao_sys_pwm_f.hw,
410*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_PWM_G]		= &a9_ao_sys_pwm_g.hw,
411*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_I2C_A]		= &a9_ao_sys_i2c_a.hw,
412*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_I2C_B]		= &a9_ao_sys_i2c_b.hw,
413*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_I2C_C]		= &a9_ao_sys_i2c_c.hw,
414*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_I2C_D]		= &a9_ao_sys_i2c_d.hw,
415*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_SED]		= &a9_ao_sys_sed.hw,
416*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_IR_CTRL]		= &a9_ao_sys_ir_ctrl.hw,
417*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_UART_B]		= &a9_ao_sys_uart_b.hw,
418*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_UART_C]		= &a9_ao_sys_uart_c.hw,
419*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_UART_D]		= &a9_ao_sys_uart_d.hw,
420*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_UART_E]		= &a9_ao_sys_uart_e.hw,
421*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_SPISG_0]		= &a9_ao_sys_spisg_0.hw,
422*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_RTC_SECURE]	= &a9_ao_sys_rtc_secure.hw,
423*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_CEC]		= &a9_ao_sys_cec.hw,
424*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_AOCPU]		= &a9_ao_sys_aocpu.hw,
425*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_SRAM]		= &a9_ao_sys_sram.hw,
426*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_SPISG_1]		= &a9_ao_sys_spisg_1.hw,
427*a1b4c3a6SJian Hu 	[CLKID_AO_SYS_SPISG_2]		= &a9_ao_sys_spisg_2.hw,
428*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_A_SEL]		= &a9_ao_pwm_a_sel.hw,
429*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_A_DIV]		= &a9_ao_pwm_a_div.hw,
430*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_A]		= &a9_ao_pwm_a.hw,
431*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_B_SEL]		= &a9_ao_pwm_b_sel.hw,
432*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_B_DIV]		= &a9_ao_pwm_b_div.hw,
433*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_B]		= &a9_ao_pwm_b.hw,
434*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_C_SEL]		= &a9_ao_pwm_c_sel.hw,
435*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_C_DIV]		= &a9_ao_pwm_c_div.hw,
436*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_C]		= &a9_ao_pwm_c.hw,
437*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_D_SEL]		= &a9_ao_pwm_d_sel.hw,
438*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_D_DIV]		= &a9_ao_pwm_d_div.hw,
439*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_D]		= &a9_ao_pwm_d.hw,
440*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_E_SEL]		= &a9_ao_pwm_e_sel.hw,
441*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_E_DIV]		= &a9_ao_pwm_e_div.hw,
442*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_E]		= &a9_ao_pwm_e.hw,
443*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_F_SEL]		= &a9_ao_pwm_f_sel.hw,
444*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_F_DIV]		= &a9_ao_pwm_f_div.hw,
445*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_F]		= &a9_ao_pwm_f.hw,
446*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_G_SEL]		= &a9_ao_pwm_g_sel.hw,
447*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_G_DIV]		= &a9_ao_pwm_g_div.hw,
448*a1b4c3a6SJian Hu 	[CLKID_AO_PWM_G]		= &a9_ao_pwm_g.hw,
449*a1b4c3a6SJian Hu 	[CLKID_AO_RTC_DUALDIV_IN]	= &a9_ao_rtc_dualdiv_in.hw,
450*a1b4c3a6SJian Hu 	[CLKID_AO_RTC_DUALDIV_DIV]	= &a9_ao_rtc_dualdiv_div.hw,
451*a1b4c3a6SJian Hu 	[CLKID_AO_RTC_DUALDIV_SEL]	= &a9_ao_rtc_dualdiv_sel.hw,
452*a1b4c3a6SJian Hu 	[CLKID_AO_RTC_DUALDIV]		= &a9_ao_rtc_dualdiv.hw,
453*a1b4c3a6SJian Hu 	[CLKID_AO_RTC]			= &a9_ao_rtc.hw,
454*a1b4c3a6SJian Hu 	[CLKID_AO_CEC_DUALDIV_IN]	= &a9_ao_cec_dualdiv_in.hw,
455*a1b4c3a6SJian Hu 	[CLKID_AO_CEC_DUALDIV_DIV]	= &a9_ao_cec_dualdiv_div.hw,
456*a1b4c3a6SJian Hu 	[CLKID_AO_CEC_DUALDIV_SEL]	= &a9_ao_cec_dualdiv_sel.hw,
457*a1b4c3a6SJian Hu 	[CLKID_AO_CEC_DUALDIV]		= &a9_ao_cec_dualdiv.hw,
458*a1b4c3a6SJian Hu 	[CLKID_AO_CEC]			= &a9_ao_cec.hw,
459*a1b4c3a6SJian Hu };
460*a1b4c3a6SJian Hu 
461*a1b4c3a6SJian Hu static const struct meson_clkc_data a9_ao_clkc_data = {
462*a1b4c3a6SJian Hu 	.hw_clks = {
463*a1b4c3a6SJian Hu 		.hws = a9_ao_hw_clks,
464*a1b4c3a6SJian Hu 		.num = ARRAY_SIZE(a9_ao_hw_clks),
465*a1b4c3a6SJian Hu 	},
466*a1b4c3a6SJian Hu };
467*a1b4c3a6SJian Hu 
468*a1b4c3a6SJian Hu static const struct of_device_id a9_ao_clkc_match_table[] = {
469*a1b4c3a6SJian Hu 	{
470*a1b4c3a6SJian Hu 		.compatible	= "amlogic,a9-aoclkc",
471*a1b4c3a6SJian Hu 		.data		= &a9_ao_clkc_data,
472*a1b4c3a6SJian Hu 	},
473*a1b4c3a6SJian Hu 	{ }
474*a1b4c3a6SJian Hu };
475*a1b4c3a6SJian Hu MODULE_DEVICE_TABLE(of, a9_ao_clkc_match_table);
476*a1b4c3a6SJian Hu 
477*a1b4c3a6SJian Hu static struct platform_driver a9_ao_clkc_driver = {
478*a1b4c3a6SJian Hu 	.probe		= meson_clkc_mmio_probe,
479*a1b4c3a6SJian Hu 	.driver		= {
480*a1b4c3a6SJian Hu 		.name	= "a9-aoclkc",
481*a1b4c3a6SJian Hu 		.of_match_table = a9_ao_clkc_match_table,
482*a1b4c3a6SJian Hu 	},
483*a1b4c3a6SJian Hu };
484*a1b4c3a6SJian Hu module_platform_driver(a9_ao_clkc_driver);
485*a1b4c3a6SJian Hu 
486*a1b4c3a6SJian Hu MODULE_DESCRIPTION("Amlogic A9 Always-ON Clock Controller driver");
487*a1b4c3a6SJian Hu MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
488*a1b4c3a6SJian Hu MODULE_LICENSE("GPL");
489*a1b4c3a6SJian Hu MODULE_IMPORT_NS("CLK_MESON");
490