xref: /openbmc/linux/drivers/clk/meson/a1-pll.c (revision 28f3be518081b2127f98105fa9735a19812a33ca)
1*28f3be51SDmitry Rokosov // SPDX-License-Identifier: GPL-2.0+
2*28f3be51SDmitry Rokosov /*
3*28f3be51SDmitry Rokosov  * Copyright (c) 2019 Amlogic, Inc. All rights reserved.
4*28f3be51SDmitry Rokosov  * Author: Jian Hu <jian.hu@amlogic.com>
5*28f3be51SDmitry Rokosov  *
6*28f3be51SDmitry Rokosov  * Copyright (c) 2023, SberDevices. All Rights Reserved.
7*28f3be51SDmitry Rokosov  * Author: Dmitry Rokosov <ddrokosov@sberdevices.ru>
8*28f3be51SDmitry Rokosov  */
9*28f3be51SDmitry Rokosov 
10*28f3be51SDmitry Rokosov #include <linux/clk-provider.h>
11*28f3be51SDmitry Rokosov #include <linux/of_device.h>
12*28f3be51SDmitry Rokosov #include <linux/platform_device.h>
13*28f3be51SDmitry Rokosov #include "a1-pll.h"
14*28f3be51SDmitry Rokosov #include "clk-regmap.h"
15*28f3be51SDmitry Rokosov 
16*28f3be51SDmitry Rokosov static struct clk_regmap fixed_pll_dco = {
17*28f3be51SDmitry Rokosov 	.data = &(struct meson_clk_pll_data){
18*28f3be51SDmitry Rokosov 		.en = {
19*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_CTRL0,
20*28f3be51SDmitry Rokosov 			.shift   = 28,
21*28f3be51SDmitry Rokosov 			.width   = 1,
22*28f3be51SDmitry Rokosov 		},
23*28f3be51SDmitry Rokosov 		.m = {
24*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_CTRL0,
25*28f3be51SDmitry Rokosov 			.shift   = 0,
26*28f3be51SDmitry Rokosov 			.width   = 8,
27*28f3be51SDmitry Rokosov 		},
28*28f3be51SDmitry Rokosov 		.n = {
29*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_CTRL0,
30*28f3be51SDmitry Rokosov 			.shift   = 10,
31*28f3be51SDmitry Rokosov 			.width   = 5,
32*28f3be51SDmitry Rokosov 		},
33*28f3be51SDmitry Rokosov 		.frac = {
34*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_CTRL1,
35*28f3be51SDmitry Rokosov 			.shift   = 0,
36*28f3be51SDmitry Rokosov 			.width   = 19,
37*28f3be51SDmitry Rokosov 		},
38*28f3be51SDmitry Rokosov 		.l = {
39*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_STS,
40*28f3be51SDmitry Rokosov 			.shift   = 31,
41*28f3be51SDmitry Rokosov 			.width   = 1,
42*28f3be51SDmitry Rokosov 		},
43*28f3be51SDmitry Rokosov 		.rst = {
44*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_FIXPLL_CTRL0,
45*28f3be51SDmitry Rokosov 			.shift   = 29,
46*28f3be51SDmitry Rokosov 			.width   = 1,
47*28f3be51SDmitry Rokosov 		},
48*28f3be51SDmitry Rokosov 	},
49*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
50*28f3be51SDmitry Rokosov 		.name = "fixed_pll_dco",
51*28f3be51SDmitry Rokosov 		.ops = &meson_clk_pll_ro_ops,
52*28f3be51SDmitry Rokosov 		.parent_data = &(const struct clk_parent_data) {
53*28f3be51SDmitry Rokosov 			.fw_name = "fixpll_in",
54*28f3be51SDmitry Rokosov 		},
55*28f3be51SDmitry Rokosov 		.num_parents = 1,
56*28f3be51SDmitry Rokosov 	},
57*28f3be51SDmitry Rokosov };
58*28f3be51SDmitry Rokosov 
59*28f3be51SDmitry Rokosov static struct clk_regmap fixed_pll = {
60*28f3be51SDmitry Rokosov 	.data = &(struct clk_regmap_gate_data){
61*28f3be51SDmitry Rokosov 		.offset = ANACTRL_FIXPLL_CTRL0,
62*28f3be51SDmitry Rokosov 		.bit_idx = 20,
63*28f3be51SDmitry Rokosov 	},
64*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data) {
65*28f3be51SDmitry Rokosov 		.name = "fixed_pll",
66*28f3be51SDmitry Rokosov 		.ops = &clk_regmap_gate_ops,
67*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
68*28f3be51SDmitry Rokosov 			&fixed_pll_dco.hw
69*28f3be51SDmitry Rokosov 		},
70*28f3be51SDmitry Rokosov 		.num_parents = 1,
71*28f3be51SDmitry Rokosov 	},
72*28f3be51SDmitry Rokosov };
73*28f3be51SDmitry Rokosov 
74*28f3be51SDmitry Rokosov static const struct pll_mult_range hifi_pll_mult_range = {
75*28f3be51SDmitry Rokosov 	.min = 32,
76*28f3be51SDmitry Rokosov 	.max = 64,
77*28f3be51SDmitry Rokosov };
78*28f3be51SDmitry Rokosov 
79*28f3be51SDmitry Rokosov static const struct reg_sequence hifi_init_regs[] = {
80*28f3be51SDmitry Rokosov 	{ .reg = ANACTRL_HIFIPLL_CTRL1, .def = 0x01800000 },
81*28f3be51SDmitry Rokosov 	{ .reg = ANACTRL_HIFIPLL_CTRL2, .def = 0x00001100 },
82*28f3be51SDmitry Rokosov 	{ .reg = ANACTRL_HIFIPLL_CTRL3, .def = 0x100a1100 },
83*28f3be51SDmitry Rokosov 	{ .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x00302000 },
84*28f3be51SDmitry Rokosov 	{ .reg = ANACTRL_HIFIPLL_CTRL0, .def = 0x01f18000 },
85*28f3be51SDmitry Rokosov };
86*28f3be51SDmitry Rokosov 
87*28f3be51SDmitry Rokosov static struct clk_regmap hifi_pll = {
88*28f3be51SDmitry Rokosov 	.data = &(struct meson_clk_pll_data){
89*28f3be51SDmitry Rokosov 		.en = {
90*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL0,
91*28f3be51SDmitry Rokosov 			.shift   = 28,
92*28f3be51SDmitry Rokosov 			.width   = 1,
93*28f3be51SDmitry Rokosov 		},
94*28f3be51SDmitry Rokosov 		.m = {
95*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL0,
96*28f3be51SDmitry Rokosov 			.shift   = 0,
97*28f3be51SDmitry Rokosov 			.width   = 8,
98*28f3be51SDmitry Rokosov 		},
99*28f3be51SDmitry Rokosov 		.n = {
100*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL0,
101*28f3be51SDmitry Rokosov 			.shift   = 10,
102*28f3be51SDmitry Rokosov 			.width   = 5,
103*28f3be51SDmitry Rokosov 		},
104*28f3be51SDmitry Rokosov 		.frac = {
105*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL1,
106*28f3be51SDmitry Rokosov 			.shift   = 0,
107*28f3be51SDmitry Rokosov 			.width   = 19,
108*28f3be51SDmitry Rokosov 		},
109*28f3be51SDmitry Rokosov 		.l = {
110*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_STS,
111*28f3be51SDmitry Rokosov 			.shift   = 31,
112*28f3be51SDmitry Rokosov 			.width   = 1,
113*28f3be51SDmitry Rokosov 		},
114*28f3be51SDmitry Rokosov 		.current_en = {
115*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL0,
116*28f3be51SDmitry Rokosov 			.shift   = 26,
117*28f3be51SDmitry Rokosov 			.width   = 1,
118*28f3be51SDmitry Rokosov 		},
119*28f3be51SDmitry Rokosov 		.l_detect = {
120*28f3be51SDmitry Rokosov 			.reg_off = ANACTRL_HIFIPLL_CTRL2,
121*28f3be51SDmitry Rokosov 			.shift   = 6,
122*28f3be51SDmitry Rokosov 			.width   = 1,
123*28f3be51SDmitry Rokosov 		},
124*28f3be51SDmitry Rokosov 		.range = &hifi_pll_mult_range,
125*28f3be51SDmitry Rokosov 		.init_regs = hifi_init_regs,
126*28f3be51SDmitry Rokosov 		.init_count = ARRAY_SIZE(hifi_init_regs),
127*28f3be51SDmitry Rokosov 	},
128*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
129*28f3be51SDmitry Rokosov 		.name = "hifi_pll",
130*28f3be51SDmitry Rokosov 		.ops = &meson_clk_pll_ops,
131*28f3be51SDmitry Rokosov 		.parent_data = &(const struct clk_parent_data) {
132*28f3be51SDmitry Rokosov 			.fw_name = "hifipll_in",
133*28f3be51SDmitry Rokosov 		},
134*28f3be51SDmitry Rokosov 		.num_parents = 1,
135*28f3be51SDmitry Rokosov 	},
136*28f3be51SDmitry Rokosov };
137*28f3be51SDmitry Rokosov 
138*28f3be51SDmitry Rokosov static struct clk_fixed_factor fclk_div2_div = {
139*28f3be51SDmitry Rokosov 	.mult = 1,
140*28f3be51SDmitry Rokosov 	.div = 2,
141*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
142*28f3be51SDmitry Rokosov 		.name = "fclk_div2_div",
143*28f3be51SDmitry Rokosov 		.ops = &clk_fixed_factor_ops,
144*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
145*28f3be51SDmitry Rokosov 			&fixed_pll.hw
146*28f3be51SDmitry Rokosov 		},
147*28f3be51SDmitry Rokosov 		.num_parents = 1,
148*28f3be51SDmitry Rokosov 	},
149*28f3be51SDmitry Rokosov };
150*28f3be51SDmitry Rokosov 
151*28f3be51SDmitry Rokosov static struct clk_regmap fclk_div2 = {
152*28f3be51SDmitry Rokosov 	.data = &(struct clk_regmap_gate_data){
153*28f3be51SDmitry Rokosov 		.offset = ANACTRL_FIXPLL_CTRL0,
154*28f3be51SDmitry Rokosov 		.bit_idx = 21,
155*28f3be51SDmitry Rokosov 	},
156*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
157*28f3be51SDmitry Rokosov 		.name = "fclk_div2",
158*28f3be51SDmitry Rokosov 		.ops = &clk_regmap_gate_ops,
159*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
160*28f3be51SDmitry Rokosov 			&fclk_div2_div.hw
161*28f3be51SDmitry Rokosov 		},
162*28f3be51SDmitry Rokosov 		.num_parents = 1,
163*28f3be51SDmitry Rokosov 		/*
164*28f3be51SDmitry Rokosov 		 * This clock is used by DDR clock in BL2 firmware
165*28f3be51SDmitry Rokosov 		 * and is required by the platform to operate correctly.
166*28f3be51SDmitry Rokosov 		 * Until the following condition are met, we need this clock to
167*28f3be51SDmitry Rokosov 		 * be marked as critical:
168*28f3be51SDmitry Rokosov 		 * a) Mark the clock used by a firmware resource, if possible
169*28f3be51SDmitry Rokosov 		 * b) CCF has a clock hand-off mechanism to make the sure the
170*28f3be51SDmitry Rokosov 		 *    clock stays on until the proper driver comes along
171*28f3be51SDmitry Rokosov 		 */
172*28f3be51SDmitry Rokosov 		.flags = CLK_IS_CRITICAL,
173*28f3be51SDmitry Rokosov 	},
174*28f3be51SDmitry Rokosov };
175*28f3be51SDmitry Rokosov 
176*28f3be51SDmitry Rokosov static struct clk_fixed_factor fclk_div3_div = {
177*28f3be51SDmitry Rokosov 	.mult = 1,
178*28f3be51SDmitry Rokosov 	.div = 3,
179*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
180*28f3be51SDmitry Rokosov 		.name = "fclk_div3_div",
181*28f3be51SDmitry Rokosov 		.ops = &clk_fixed_factor_ops,
182*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
183*28f3be51SDmitry Rokosov 			&fixed_pll.hw
184*28f3be51SDmitry Rokosov 		},
185*28f3be51SDmitry Rokosov 		.num_parents = 1,
186*28f3be51SDmitry Rokosov 	},
187*28f3be51SDmitry Rokosov };
188*28f3be51SDmitry Rokosov 
189*28f3be51SDmitry Rokosov static struct clk_regmap fclk_div3 = {
190*28f3be51SDmitry Rokosov 	.data = &(struct clk_regmap_gate_data){
191*28f3be51SDmitry Rokosov 		.offset = ANACTRL_FIXPLL_CTRL0,
192*28f3be51SDmitry Rokosov 		.bit_idx = 22,
193*28f3be51SDmitry Rokosov 	},
194*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
195*28f3be51SDmitry Rokosov 		.name = "fclk_div3",
196*28f3be51SDmitry Rokosov 		.ops = &clk_regmap_gate_ops,
197*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
198*28f3be51SDmitry Rokosov 			&fclk_div3_div.hw
199*28f3be51SDmitry Rokosov 		},
200*28f3be51SDmitry Rokosov 		.num_parents = 1,
201*28f3be51SDmitry Rokosov 		/*
202*28f3be51SDmitry Rokosov 		 * This clock is used by APB bus which is set in boot ROM code
203*28f3be51SDmitry Rokosov 		 * and is required by the platform to operate correctly.
204*28f3be51SDmitry Rokosov 		 */
205*28f3be51SDmitry Rokosov 		.flags = CLK_IS_CRITICAL,
206*28f3be51SDmitry Rokosov 	},
207*28f3be51SDmitry Rokosov };
208*28f3be51SDmitry Rokosov 
209*28f3be51SDmitry Rokosov static struct clk_fixed_factor fclk_div5_div = {
210*28f3be51SDmitry Rokosov 	.mult = 1,
211*28f3be51SDmitry Rokosov 	.div = 5,
212*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
213*28f3be51SDmitry Rokosov 		.name = "fclk_div5_div",
214*28f3be51SDmitry Rokosov 		.ops = &clk_fixed_factor_ops,
215*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
216*28f3be51SDmitry Rokosov 			&fixed_pll.hw
217*28f3be51SDmitry Rokosov 		},
218*28f3be51SDmitry Rokosov 		.num_parents = 1,
219*28f3be51SDmitry Rokosov 	},
220*28f3be51SDmitry Rokosov };
221*28f3be51SDmitry Rokosov 
222*28f3be51SDmitry Rokosov static struct clk_regmap fclk_div5 = {
223*28f3be51SDmitry Rokosov 	.data = &(struct clk_regmap_gate_data){
224*28f3be51SDmitry Rokosov 		.offset = ANACTRL_FIXPLL_CTRL0,
225*28f3be51SDmitry Rokosov 		.bit_idx = 23,
226*28f3be51SDmitry Rokosov 	},
227*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
228*28f3be51SDmitry Rokosov 		.name = "fclk_div5",
229*28f3be51SDmitry Rokosov 		.ops = &clk_regmap_gate_ops,
230*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
231*28f3be51SDmitry Rokosov 			&fclk_div5_div.hw
232*28f3be51SDmitry Rokosov 		},
233*28f3be51SDmitry Rokosov 		.num_parents = 1,
234*28f3be51SDmitry Rokosov 		/*
235*28f3be51SDmitry Rokosov 		 * This clock is used by AXI bus which setted in Romcode
236*28f3be51SDmitry Rokosov 		 * and is required by the platform to operate correctly.
237*28f3be51SDmitry Rokosov 		 */
238*28f3be51SDmitry Rokosov 		.flags = CLK_IS_CRITICAL,
239*28f3be51SDmitry Rokosov 	},
240*28f3be51SDmitry Rokosov };
241*28f3be51SDmitry Rokosov 
242*28f3be51SDmitry Rokosov static struct clk_fixed_factor fclk_div7_div = {
243*28f3be51SDmitry Rokosov 	.mult = 1,
244*28f3be51SDmitry Rokosov 	.div = 7,
245*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
246*28f3be51SDmitry Rokosov 		.name = "fclk_div7_div",
247*28f3be51SDmitry Rokosov 		.ops = &clk_fixed_factor_ops,
248*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
249*28f3be51SDmitry Rokosov 			&fixed_pll.hw
250*28f3be51SDmitry Rokosov 		},
251*28f3be51SDmitry Rokosov 		.num_parents = 1,
252*28f3be51SDmitry Rokosov 	},
253*28f3be51SDmitry Rokosov };
254*28f3be51SDmitry Rokosov 
255*28f3be51SDmitry Rokosov static struct clk_regmap fclk_div7 = {
256*28f3be51SDmitry Rokosov 	.data = &(struct clk_regmap_gate_data){
257*28f3be51SDmitry Rokosov 		.offset = ANACTRL_FIXPLL_CTRL0,
258*28f3be51SDmitry Rokosov 		.bit_idx = 24,
259*28f3be51SDmitry Rokosov 	},
260*28f3be51SDmitry Rokosov 	.hw.init = &(struct clk_init_data){
261*28f3be51SDmitry Rokosov 		.name = "fclk_div7",
262*28f3be51SDmitry Rokosov 		.ops = &clk_regmap_gate_ops,
263*28f3be51SDmitry Rokosov 		.parent_hws = (const struct clk_hw *[]) {
264*28f3be51SDmitry Rokosov 			&fclk_div7_div.hw
265*28f3be51SDmitry Rokosov 		},
266*28f3be51SDmitry Rokosov 		.num_parents = 1,
267*28f3be51SDmitry Rokosov 	},
268*28f3be51SDmitry Rokosov };
269*28f3be51SDmitry Rokosov 
270*28f3be51SDmitry Rokosov /* Array of all clocks registered by this provider */
271*28f3be51SDmitry Rokosov static struct clk_hw_onecell_data a1_pll_clks = {
272*28f3be51SDmitry Rokosov 	.hws = {
273*28f3be51SDmitry Rokosov 		[CLKID_FIXED_PLL_DCO]	= &fixed_pll_dco.hw,
274*28f3be51SDmitry Rokosov 		[CLKID_FIXED_PLL]	= &fixed_pll.hw,
275*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV2_DIV]	= &fclk_div2_div.hw,
276*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV3_DIV]	= &fclk_div3_div.hw,
277*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV5_DIV]	= &fclk_div5_div.hw,
278*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV7_DIV]	= &fclk_div7_div.hw,
279*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV2]	= &fclk_div2.hw,
280*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV3]	= &fclk_div3.hw,
281*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV5]	= &fclk_div5.hw,
282*28f3be51SDmitry Rokosov 		[CLKID_FCLK_DIV7]	= &fclk_div7.hw,
283*28f3be51SDmitry Rokosov 		[CLKID_HIFI_PLL]	= &hifi_pll.hw,
284*28f3be51SDmitry Rokosov 		[NR_PLL_CLKS]		= NULL,
285*28f3be51SDmitry Rokosov 	},
286*28f3be51SDmitry Rokosov 	.num = NR_PLL_CLKS,
287*28f3be51SDmitry Rokosov };
288*28f3be51SDmitry Rokosov 
289*28f3be51SDmitry Rokosov static struct clk_regmap *const a1_pll_regmaps[] = {
290*28f3be51SDmitry Rokosov 	&fixed_pll_dco,
291*28f3be51SDmitry Rokosov 	&fixed_pll,
292*28f3be51SDmitry Rokosov 	&fclk_div2,
293*28f3be51SDmitry Rokosov 	&fclk_div3,
294*28f3be51SDmitry Rokosov 	&fclk_div5,
295*28f3be51SDmitry Rokosov 	&fclk_div7,
296*28f3be51SDmitry Rokosov 	&hifi_pll,
297*28f3be51SDmitry Rokosov };
298*28f3be51SDmitry Rokosov 
299*28f3be51SDmitry Rokosov static struct regmap_config a1_pll_regmap_cfg = {
300*28f3be51SDmitry Rokosov 	.reg_bits   = 32,
301*28f3be51SDmitry Rokosov 	.val_bits   = 32,
302*28f3be51SDmitry Rokosov 	.reg_stride = 4,
303*28f3be51SDmitry Rokosov };
304*28f3be51SDmitry Rokosov 
305*28f3be51SDmitry Rokosov static int meson_a1_pll_probe(struct platform_device *pdev)
306*28f3be51SDmitry Rokosov {
307*28f3be51SDmitry Rokosov 	struct device *dev = &pdev->dev;
308*28f3be51SDmitry Rokosov 	void __iomem *base;
309*28f3be51SDmitry Rokosov 	struct regmap *map;
310*28f3be51SDmitry Rokosov 	int clkid, i, err;
311*28f3be51SDmitry Rokosov 
312*28f3be51SDmitry Rokosov 	base = devm_platform_ioremap_resource(pdev, 0);
313*28f3be51SDmitry Rokosov 	if (IS_ERR(base))
314*28f3be51SDmitry Rokosov 		return dev_err_probe(dev, PTR_ERR(base),
315*28f3be51SDmitry Rokosov 				     "can't ioremap resource\n");
316*28f3be51SDmitry Rokosov 
317*28f3be51SDmitry Rokosov 	map = devm_regmap_init_mmio(dev, base, &a1_pll_regmap_cfg);
318*28f3be51SDmitry Rokosov 	if (IS_ERR(map))
319*28f3be51SDmitry Rokosov 		return dev_err_probe(dev, PTR_ERR(map),
320*28f3be51SDmitry Rokosov 				     "can't init regmap mmio region\n");
321*28f3be51SDmitry Rokosov 
322*28f3be51SDmitry Rokosov 	/* Populate regmap for the regmap backed clocks */
323*28f3be51SDmitry Rokosov 	for (i = 0; i < ARRAY_SIZE(a1_pll_regmaps); i++)
324*28f3be51SDmitry Rokosov 		a1_pll_regmaps[i]->map = map;
325*28f3be51SDmitry Rokosov 
326*28f3be51SDmitry Rokosov 	/* Register clocks */
327*28f3be51SDmitry Rokosov 	for (clkid = 0; clkid < a1_pll_clks.num; clkid++) {
328*28f3be51SDmitry Rokosov 		err = devm_clk_hw_register(dev, a1_pll_clks.hws[clkid]);
329*28f3be51SDmitry Rokosov 		if (err)
330*28f3be51SDmitry Rokosov 			return dev_err_probe(dev, err,
331*28f3be51SDmitry Rokosov 					     "clock[%d] registration failed\n",
332*28f3be51SDmitry Rokosov 					     clkid);
333*28f3be51SDmitry Rokosov 	}
334*28f3be51SDmitry Rokosov 
335*28f3be51SDmitry Rokosov 	return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
336*28f3be51SDmitry Rokosov 					   &a1_pll_clks);
337*28f3be51SDmitry Rokosov }
338*28f3be51SDmitry Rokosov 
339*28f3be51SDmitry Rokosov static const struct of_device_id a1_pll_clkc_match_table[] = {
340*28f3be51SDmitry Rokosov 	{ .compatible = "amlogic,a1-pll-clkc", },
341*28f3be51SDmitry Rokosov 	{}
342*28f3be51SDmitry Rokosov };
343*28f3be51SDmitry Rokosov MODULE_DEVICE_TABLE(of, a1_pll_clkc_match_table);
344*28f3be51SDmitry Rokosov 
345*28f3be51SDmitry Rokosov static struct platform_driver a1_pll_clkc_driver = {
346*28f3be51SDmitry Rokosov 	.probe = meson_a1_pll_probe,
347*28f3be51SDmitry Rokosov 	.driver = {
348*28f3be51SDmitry Rokosov 		.name = "a1-pll-clkc",
349*28f3be51SDmitry Rokosov 		.of_match_table = a1_pll_clkc_match_table,
350*28f3be51SDmitry Rokosov 	},
351*28f3be51SDmitry Rokosov };
352*28f3be51SDmitry Rokosov 
353*28f3be51SDmitry Rokosov module_platform_driver(a1_pll_clkc_driver);
354*28f3be51SDmitry Rokosov MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
355*28f3be51SDmitry Rokosov MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
356*28f3be51SDmitry Rokosov MODULE_LICENSE("GPL");
357