File Index
Files and directories
Sign in
FILE

s4-pll.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/meson/s4-pll.c C
  1// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
  2/*
  3 * Amlogic S4 PLL Clock Controller Driver
  4 *
  5 * Copyright (c) 2022-2023 Amlogic, inc. All rights reserved
  6 * Author: Yu Tu <yu.tu@amlogic.com>
  7 */
  8
  9#include <linux/clk-provider.h>
 10#include <linux/of_device.h>
 11#include <linux/platform_device.h>
 12
 13#include "clk-mpll.h"
 14#include "clk-pll.h"
 15#include "clk-regmap.h"
 16#include "meson-clkc-utils.h"
 17#include <dt-bindings/clock/amlogic,s4-pll-clkc.h>
 18
 19#define ANACTRL_FIXPLL_CTRL0                       0x040
 20#define ANACTRL_FIXPLL_CTRL1                       0x044
 21#define ANACTRL_FIXPLL_CTRL3                       0x04c
 22#define ANACTRL_GP0PLL_CTRL0                       0x080
 23#define ANACTRL_GP0PLL_CTRL1                       0x084
 24#define ANACTRL_GP0PLL_CTRL2                       0x088
 25#define ANACTRL_GP0PLL_CTRL3                       0x08c
 26#define ANACTRL_GP0PLL_CTRL4                       0x090
 27#define ANACTRL_GP0PLL_CTRL5                       0x094
 28#define ANACTRL_GP0PLL_CTRL6                       0x098
 29#define ANACTRL_HIFIPLL_CTRL0                      0x100
 30#define ANACTRL_HIFIPLL_CTRL1                      0x104
 31#define ANACTRL_HIFIPLL_CTRL2                      0x108
 32#define ANACTRL_HIFIPLL_CTRL3                      0x10c
 33#define ANACTRL_HIFIPLL_CTRL4                      0x110
 34#define ANACTRL_HIFIPLL_CTRL5                      0x114
 35#define ANACTRL_HIFIPLL_CTRL6                      0x118
 36#define ANACTRL_MPLL_CTRL0                         0x180
 37#define ANACTRL_MPLL_CTRL1                         0x184
 38#define ANACTRL_MPLL_CTRL2                         0x188
 39#define ANACTRL_MPLL_CTRL3                         0x18c
 40#define ANACTRL_MPLL_CTRL4                         0x190
 41#define ANACTRL_MPLL_CTRL5                         0x194
 42#define ANACTRL_MPLL_CTRL6                         0x198
 43#define ANACTRL_MPLL_CTRL7                         0x19c
 44#define ANACTRL_MPLL_CTRL8                         0x1a0
 45#define ANACTRL_HDMIPLL_CTRL0                      0x1c0
 46
 47/*
 48 * These clock are a fixed value (fixed_pll is 2GHz) that is initialized by ROMcode.
 49 * The chip was changed fixed pll for security reasons. Fixed PLL registers are not writable
 50 * in the kernel phase. Write of fixed PLL-related register will cause the system to crash.
 51 * Meanwhile, these clock won't ever change at runtime.
 52 * For the above reasons, we can only use ro_ops for fixed PLL related clocks.
 53 */
 54static struct clk_regmap s4_fixed_pll_dco = {
 55	.data = &(struct meson_clk_pll_data){
 56		.en = {
 57			.reg_off = ANACTRL_FIXPLL_CTRL0,
 58			.shift   = 28,
 59			.width   = 1,
 60		},
 61		.m = {
 62			.reg_off = ANACTRL_FIXPLL_CTRL0,
 63			.shift   = 0,
 64			.width   = 8,
 65		},
 66		.frac = {
 67			.reg_off = ANACTRL_FIXPLL_CTRL1,
 68			.shift   = 0,
 69			.width   = 17,
 70		},
 71		.n = {
 72			.reg_off = ANACTRL_FIXPLL_CTRL0,
 73			.shift   = 10,
 74			.width   = 5,
 75		},
 76		.l = {
 77			.reg_off = ANACTRL_FIXPLL_CTRL0,
 78			.shift   = 31,
 79			.width   = 1,
 80		},
 81		.rst = {
 82			.reg_off = ANACTRL_FIXPLL_CTRL0,
 83			.shift   = 29,
 84			.width   = 1,
 85		},
 86	},
 87	.hw.init = &(struct clk_init_data){
 88		.name = "fixed_pll_dco",
 89		.ops = &meson_clk_pll_ro_ops,
 90		.parent_data = (const struct clk_parent_data []) {
 91			{ .fw_name = "xtal", }
 92		},
 93		.num_parents = 1,
 94	},
 95};
 96
 97static struct clk_regmap s4_fixed_pll = {
 98	.data = &(struct clk_regmap_div_data){
 99		.offset = ANACTRL_FIXPLL_CTRL0,
100		.shift = 16,
101		.width = 2,
102		.flags = CLK_DIVIDER_POWER_OF_TWO,
103	},
104	.hw.init = &(struct clk_init_data){
105		.name = "fixed_pll",
106		.ops = &clk_regmap_divider_ro_ops,
107		.parent_hws = (const struct clk_hw *[]) {
108			&s4_fixed_pll_dco.hw
109		},
110		.num_parents = 1,
111		/*
112		 * This clock won't ever change at runtime so
113		 * CLK_SET_RATE_PARENT is not required
114		 */
115	},
116};
117
118static struct clk_fixed_factor s4_fclk_div2_div = {
119	.mult = 1,
120	.div = 2,
121	.hw.init = &(struct clk_init_data){
122		.name = "fclk_div2_div",
123		.ops = &clk_fixed_factor_ops,
124		.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
125		.num_parents = 1,
126	},
127};
128
129static struct clk_regmap s4_fclk_div2 = {
130	.data = &(struct clk_regmap_gate_data){
131		.offset = ANACTRL_FIXPLL_CTRL1,
132		.bit_idx = 24,
133	},
134	.hw.init = &(struct clk_init_data){
135		.name = "fclk_div2",
136		.ops = &clk_regmap_gate_ro_ops,
137		.parent_hws = (const struct clk_hw *[]) {
138			&s4_fclk_div2_div.hw
139		},
140		.num_parents = 1,
141	},
142};
143
144static struct clk_fixed_factor s4_fclk_div3_div = {
145	.mult = 1,
146	.div = 3,
147	.hw.init = &(struct clk_init_data){
148		.name = "fclk_div3_div",
149		.ops = &clk_fixed_factor_ops,
150		.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
151		.num_parents = 1,
152	},
153};
154
155static struct clk_regmap s4_fclk_div3 = {
156	.data = &(struct clk_regmap_gate_data){
157		.offset = ANACTRL_FIXPLL_CTRL1,
158		.bit_idx = 20,
159	},
160	.hw.init = &(struct clk_init_data){
161		.name = "fclk_div3",
162		.ops = &clk_regmap_gate_ro_ops,
163		.parent_hws = (const struct clk_hw *[]) {
164			&s4_fclk_div3_div.hw
165		},
166		.num_parents = 1,
167	},
168};
169
170static struct clk_fixed_factor s4_fclk_div4_div = {
171	.mult = 1,
172	.div = 4,
173	.hw.init = &(struct clk_init_data){
174		.name = "fclk_div4_div",
175		.ops = &clk_fixed_factor_ops,
176		.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
177		.num_parents = 1,
178	},
179};
180
181static struct clk_regmap s4_fclk_div4 = {
182	.data = &(struct clk_regmap_gate_data){
183		.offset = ANACTRL_FIXPLL_CTRL1,
184		.bit_idx = 21,
185	},
186	.hw.init = &(struct clk_init_data){
187		.name = "fclk_div4",
188		.ops = &clk_regmap_gate_ro_ops,
189		.parent_hws = (const struct clk_hw *[]) {
190			&s4_fclk_div4_div.hw
191		},
192		.num_parents = 1,
193	},
194};
195
196static struct clk_fixed_factor s4_fclk_div5_div = {
197	.mult = 1,
198	.div = 5,
199	.hw.init = &(struct clk_init_data){
200		.name = "fclk_div5_div",
201		.ops = &clk_fixed_factor_ops,
202		.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
203		.num_parents = 1,
204	},
205};
206
207static struct clk_regmap s4_fclk_div5 = {
208	.data = &(struct clk_regmap_gate_data){
209		.offset = ANACTRL_FIXPLL_CTRL1,
210		.bit_idx = 22,
211	},
212	.hw.init = &(struct clk_init_data){
213		.name = "fclk_div5",
214		.ops = &clk_regmap_gate_ro_ops,
215		.parent_hws = (const struct clk_hw *[]) {
216			&s4_fclk_div5_div.hw
217		},
218		.num_parents = 1,
219	},
220};
221
222static struct clk_fixed_factor s4_fclk_div7_div = {
223	.mult = 1,
224	.div = 7,
225	.hw.init = &(struct clk_init_data){
226		.name = "fclk_div7_div",
227		.ops = &clk_fixed_factor_ops,
228		.parent_hws = (const struct clk_hw *[]) { &s4_fixed_pll.hw },
229		.num_parents = 1,
230	},
231};
232
233static struct clk_regmap s4_fclk_div7 = {
234	.data = &(struct clk_regmap_gate_data){
235		.offset = ANACTRL_FIXPLL_CTRL1,
236		.bit_idx = 23,
237	},
238	.hw.init = &(struct clk_init_data){
239		.name = "fclk_div7",
240		.ops = &clk_regmap_gate_ro_ops,
241		.parent_hws = (const struct clk_hw *[]) {
242			&s4_fclk_div7_div.hw
243		},
244		.num_parents = 1,
245	},
246};
247
248static struct clk_fixed_factor s4_fclk_div2p5_div = {
249	.mult = 2,
250	.div = 5,
251	.hw.init = &(struct clk_init_data){
252		.name = "fclk_div2p5_div",
253		.ops = &clk_fixed_factor_ops,
254		.parent_hws = (const struct clk_hw *[]) {
255			&s4_fixed_pll.hw
256		},
257		.num_parents = 1,
258	},
259};
260
261static struct clk_regmap s4_fclk_div2p5 = {
262	.data = &(struct clk_regmap_gate_data){
263		.offset = ANACTRL_FIXPLL_CTRL1,
264		.bit_idx = 25,
265	},
266	.hw.init = &(struct clk_init_data){
267		.name = "fclk_div2p5",
268		.ops = &clk_regmap_gate_ro_ops,
269		.parent_hws = (const struct clk_hw *[]) {
270			&s4_fclk_div2p5_div.hw
271		},
272		.num_parents = 1,
273	},
274};
275
276static const struct pll_mult_range s4_gp0_pll_mult_range = {
277	.min = 125,
278	.max = 250,
279};
280
281/*
282 * Internal gp0 pll emulation configuration parameters
283 */
284static const struct reg_sequence s4_gp0_pll_init_regs[] = {
285	{ .reg = ANACTRL_GP0PLL_CTRL1,	.def = 0x00000000 },
286	{ .reg = ANACTRL_GP0PLL_CTRL2,	.def = 0x00000000 },
287	{ .reg = ANACTRL_GP0PLL_CTRL3,	.def = 0x48681c00 },
288	{ .reg = ANACTRL_GP0PLL_CTRL4,	.def = 0x88770290 },
289	{ .reg = ANACTRL_GP0PLL_CTRL5,	.def = 0x39272000 },
290	{ .reg = ANACTRL_GP0PLL_CTRL6,	.def = 0x56540000 }
291};
292
293static struct clk_regmap s4_gp0_pll_dco = {
294	.data = &(struct meson_clk_pll_data){
295		.en = {
296			.reg_off = ANACTRL_GP0PLL_CTRL0,
297			.shift   = 28,
298			.width   = 1,
299		},
300		.m = {
301			.reg_off = ANACTRL_GP0PLL_CTRL0,
302			.shift   = 0,
303			.width   = 8,
304		},
305		.n = {
306			.reg_off = ANACTRL_GP0PLL_CTRL0,
307			.shift   = 10,
308			.width   = 5,
309		},
310		.l = {
311			.reg_off = ANACTRL_GP0PLL_CTRL0,
312			.shift   = 31,
313			.width   = 1,
314		},
315		.rst = {
316			.reg_off = ANACTRL_GP0PLL_CTRL0,
317			.shift   = 29,
318			.width   = 1,
319		},
320		.range = &s4_gp0_pll_mult_range,
321		.init_regs = s4_gp0_pll_init_regs,
322		.init_count = ARRAY_SIZE(s4_gp0_pll_init_regs),
323	},
324	.hw.init = &(struct clk_init_data){
325		.name = "gp0_pll_dco",
326		.ops = &meson_clk_pll_ops,
327		.parent_data = (const struct clk_parent_data []) {
328			{ .fw_name = "xtal", }
329		},
330		.num_parents = 1,
331	},
332};
333
334static struct clk_regmap s4_gp0_pll = {
335	.data = &(struct clk_regmap_div_data){
336		.offset = ANACTRL_GP0PLL_CTRL0,
337		.shift = 16,
338		.width = 3,
339		.flags = (CLK_DIVIDER_POWER_OF_TWO |
340			  CLK_DIVIDER_ROUND_CLOSEST),
341	},
342	.hw.init = &(struct clk_init_data){
343		.name = "gp0_pll",
344		.ops = &clk_regmap_divider_ops,
345		.parent_hws = (const struct clk_hw *[]) {
346			&s4_gp0_pll_dco.hw
347		},
348		.num_parents = 1,
349		.flags = CLK_SET_RATE_PARENT,
350	},
351};
352
353/*
354 * Internal hifi pll emulation configuration parameters
355 */
356static const struct reg_sequence s4_hifi_pll_init_regs[] = {
357	{ .reg = ANACTRL_HIFIPLL_CTRL2,	.def = 0x00000000 },
358	{ .reg = ANACTRL_HIFIPLL_CTRL3,	.def = 0x6a285c00 },
359	{ .reg = ANACTRL_HIFIPLL_CTRL4,	.def = 0x65771290 },
360	{ .reg = ANACTRL_HIFIPLL_CTRL5,	.def = 0x39272000 },
361	{ .reg = ANACTRL_HIFIPLL_CTRL6,	.def = 0x56540000 }
362};
363
364static struct clk_regmap s4_hifi_pll_dco = {
365	.data = &(struct meson_clk_pll_data){
366		.en = {
367			.reg_off = ANACTRL_HIFIPLL_CTRL0,
368			.shift   = 28,
369			.width   = 1,
370		},
371		.m = {
372			.reg_off = ANACTRL_HIFIPLL_CTRL0,
373			.shift   = 0,
374			.width   = 8,
375		},
376		.n = {
377			.reg_off = ANACTRL_HIFIPLL_CTRL0,
378			.shift   = 10,
379			.width   = 5,
380		},
381		.frac = {
382			.reg_off = ANACTRL_HIFIPLL_CTRL1,
383			.shift   = 0,
384			.width   = 17,
385		},
386		.l = {
387			.reg_off = ANACTRL_HIFIPLL_CTRL0,
388			.shift   = 31,
389			.width   = 1,
390		},
391		.rst = {
392			.reg_off = ANACTRL_HIFIPLL_CTRL0,
393			.shift   = 29,
394			.width   = 1,
395		},
396		.range = &s4_gp0_pll_mult_range,
397		.init_regs = s4_hifi_pll_init_regs,
398		.init_count = ARRAY_SIZE(s4_hifi_pll_init_regs),
399		.frac_max = 100000,
400		.flags = CLK_MESON_PLL_ROUND_CLOSEST,
401	},
402	.hw.init = &(struct clk_init_data){
403		.name = "hifi_pll_dco",
404		.ops = &meson_clk_pll_ops,
405		.parent_data = (const struct clk_parent_data []) {
406			{ .fw_name = "xtal", }
407		},
408		.num_parents = 1,
409	},
410};
411
412static struct clk_regmap s4_hifi_pll = {
413	.data = &(struct clk_regmap_div_data){
414		.offset = ANACTRL_HIFIPLL_CTRL0,
415		.shift = 16,
416		.width = 2,
417		.flags = (CLK_DIVIDER_POWER_OF_TWO |
418			  CLK_DIVIDER_ROUND_CLOSEST),
419	},
420	.hw.init = &(struct clk_init_data){
421		.name = "hifi_pll",
422		.ops = &clk_regmap_divider_ops,
423		.parent_hws = (const struct clk_hw *[]) {
424			&s4_hifi_pll_dco.hw
425		},
426		.num_parents = 1,
427		.flags = CLK_SET_RATE_PARENT,
428	},
429};
430
431static struct clk_regmap s4_hdmi_pll_dco = {
432	.data = &(struct meson_clk_pll_data){
433		.en = {
434			.reg_off = ANACTRL_HDMIPLL_CTRL0,
435			.shift   = 28,
436			.width   = 1,
437		},
438		.m = {
439			.reg_off = ANACTRL_HDMIPLL_CTRL0,
440			.shift   = 0,
441			.width   = 8,
442		},
443		.n = {
444			.reg_off = ANACTRL_HDMIPLL_CTRL0,
445			.shift   = 10,
446			.width   = 5,
447		},
448		.l = {
449			.reg_off = ANACTRL_HDMIPLL_CTRL0,
450			.shift   = 31,
451			.width   = 1,
452		},
453		.rst = {
454			.reg_off = ANACTRL_HDMIPLL_CTRL0,
455			.shift   = 29,
456			.width   = 1,
457		},
458		.range = &s4_gp0_pll_mult_range,
459	},
460	.hw.init = &(struct clk_init_data){
461		.name = "hdmi_pll_dco",
462		.ops = &meson_clk_pll_ops,
463		.parent_data = (const struct clk_parent_data []) {
464			{ .fw_name = "xtal", }
465		},
466		.num_parents = 1,
467	},
468};
469
470static struct clk_regmap s4_hdmi_pll_od = {
471	.data = &(struct clk_regmap_div_data){
472		.offset = ANACTRL_HDMIPLL_CTRL0,
473		.shift = 16,
474		.width = 4,
475		.flags = CLK_DIVIDER_POWER_OF_TWO,
476	},
477	.hw.init = &(struct clk_init_data){
478		.name = "hdmi_pll_od",
479		.ops = &clk_regmap_divider_ops,
480		.parent_hws = (const struct clk_hw *[]) {
481			&s4_hdmi_pll_dco.hw
482		},
483		.num_parents = 1,
484		.flags = CLK_SET_RATE_PARENT,
485	},
486};
487
488static struct clk_regmap s4_hdmi_pll = {
489	.data = &(struct clk_regmap_div_data){
490		.offset = ANACTRL_HDMIPLL_CTRL0,
491		.shift = 20,
492		.width = 2,
493		.flags = CLK_DIVIDER_POWER_OF_TWO,
494	},
495	.hw.init = &(struct clk_init_data){
496		.name = "hdmi_pll",
497		.ops = &clk_regmap_divider_ops,
498		.parent_hws = (const struct clk_hw *[]) {
499			&s4_hdmi_pll_od.hw
500		},
501		.num_parents = 1,
502		.flags = CLK_SET_RATE_PARENT,
503	},
504};
505
506static struct clk_fixed_factor s4_mpll_50m_div = {
507	.mult = 1,
508	.div = 80,
509	.hw.init = &(struct clk_init_data){
510		.name = "mpll_50m_div",
511		.ops = &clk_fixed_factor_ops,
512		.parent_hws = (const struct clk_hw *[]) {
513			&s4_fixed_pll_dco.hw
514		},
515		.num_parents = 1,
516	},
517};
518
519static struct clk_regmap s4_mpll_50m = {
520	.data = &(struct clk_regmap_mux_data){
521		.offset = ANACTRL_FIXPLL_CTRL3,
522		.mask = 0x1,
523		.shift = 5,
524	},
525	.hw.init = &(struct clk_init_data){
526		.name = "mpll_50m",
527		.ops = &clk_regmap_mux_ro_ops,
528		.parent_data = (const struct clk_parent_data []) {
529			{ .fw_name = "xtal", },
530			{ .hw = &s4_mpll_50m_div.hw },
531		},
532		.num_parents = 2,
533	},
534};
535
536static struct clk_fixed_factor s4_mpll_prediv = {
537	.mult = 1,
538	.div = 2,
539	.hw.init = &(struct clk_init_data){
540		.name = "mpll_prediv",
541		.ops = &clk_fixed_factor_ops,
542		.parent_hws = (const struct clk_hw *[]) {
543			&s4_fixed_pll_dco.hw
544		},
545		.num_parents = 1,
546	},
547};
548
549static const struct reg_sequence s4_mpll0_init_regs[] = {
550	{ .reg = ANACTRL_MPLL_CTRL2, .def = 0x40000033 }
551};
552
553static struct clk_regmap s4_mpll0_div = {
554	.data = &(struct meson_clk_mpll_data){
555		.sdm = {
556			.reg_off = ANACTRL_MPLL_CTRL1,
557			.shift   = 0,
558			.width   = 14,
559		},
560		.sdm_en = {
561			.reg_off = ANACTRL_MPLL_CTRL1,
562			.shift   = 30,
563			.width	 = 1,
564		},
565		.n2 = {
566			.reg_off = ANACTRL_MPLL_CTRL1,
567			.shift   = 20,
568			.width   = 9,
569		},
570		.ssen = {
571			.reg_off = ANACTRL_MPLL_CTRL1,
572			.shift   = 29,
573			.width	 = 1,
574		},
575		.init_regs = s4_mpll0_init_regs,
576		.init_count = ARRAY_SIZE(s4_mpll0_init_regs),
577	},
578	.hw.init = &(struct clk_init_data){
579		.name = "mpll0_div",
580		.ops = &meson_clk_mpll_ops,
581		.parent_hws = (const struct clk_hw *[]) {
582			&s4_mpll_prediv.hw
583		},
584		.num_parents = 1,
585	},
586};
587
588static struct clk_regmap s4_mpll0 = {
589	.data = &(struct clk_regmap_gate_data){
590		.offset = ANACTRL_MPLL_CTRL1,
591		.bit_idx = 31,
592	},
593	.hw.init = &(struct clk_init_data){
594		.name = "mpll0",
595		.ops = &clk_regmap_gate_ops,
596		.parent_hws = (const struct clk_hw *[]) { &s4_mpll0_div.hw },
597		.num_parents = 1,
598		.flags = CLK_SET_RATE_PARENT,
599	},
600};
601
602static const struct reg_sequence s4_mpll1_init_regs[] = {
603	{ .reg = ANACTRL_MPLL_CTRL4,	.def = 0x40000033 }
604};
605
606static struct clk_regmap s4_mpll1_div = {
607	.data = &(struct meson_clk_mpll_data){
608		.sdm = {
609			.reg_off = ANACTRL_MPLL_CTRL3,
610			.shift   = 0,
611			.width   = 14,
612		},
613		.sdm_en = {
614			.reg_off = ANACTRL_MPLL_CTRL3,
615			.shift   = 30,
616			.width	 = 1,
617		},
618		.n2 = {
619			.reg_off = ANACTRL_MPLL_CTRL3,
620			.shift   = 20,
621			.width   = 9,
622		},
623		.ssen = {
624			.reg_off = ANACTRL_MPLL_CTRL3,
625			.shift   = 29,
626			.width	 = 1,
627		},
628		.init_regs = s4_mpll1_init_regs,
629		.init_count = ARRAY_SIZE(s4_mpll1_init_regs),
630	},
631	.hw.init = &(struct clk_init_data){
632		.name = "mpll1_div",
633		.ops = &meson_clk_mpll_ops,
634		.parent_hws = (const struct clk_hw *[]) {
635			&s4_mpll_prediv.hw
636		},
637		.num_parents = 1,
638	},
639};
640
641static struct clk_regmap s4_mpll1 = {
642	.data = &(struct clk_regmap_gate_data){
643		.offset = ANACTRL_MPLL_CTRL3,
644		.bit_idx = 31,
645	},
646	.hw.init = &(struct clk_init_data){
647		.name = "mpll1",
648		.ops = &clk_regmap_gate_ops,
649		.parent_hws = (const struct clk_hw *[]) { &s4_mpll1_div.hw },
650		.num_parents = 1,
651		.flags = CLK_SET_RATE_PARENT,
652	},
653};
654
655static const struct reg_sequence s4_mpll2_init_regs[] = {
656	{ .reg = ANACTRL_MPLL_CTRL6, .def = 0x40000033 }
657};
658
659static struct clk_regmap s4_mpll2_div = {
660	.data = &(struct meson_clk_mpll_data){
661		.sdm = {
662			.reg_off = ANACTRL_MPLL_CTRL5,
663			.shift   = 0,
664			.width   = 14,
665		},
666		.sdm_en = {
667			.reg_off = ANACTRL_MPLL_CTRL5,
668			.shift   = 30,
669			.width	 = 1,
670		},
671		.n2 = {
672			.reg_off = ANACTRL_MPLL_CTRL5,
673			.shift   = 20,
674			.width   = 9,
675		},
676		.ssen = {
677			.reg_off = ANACTRL_MPLL_CTRL5,
678			.shift   = 29,
679			.width	 = 1,
680		},
681		.init_regs = s4_mpll2_init_regs,
682		.init_count = ARRAY_SIZE(s4_mpll2_init_regs),
683	},
684	.hw.init = &(struct clk_init_data){
685		.name = "mpll2_div",
686		.ops = &meson_clk_mpll_ops,
687		.parent_hws = (const struct clk_hw *[]) {
688			&s4_mpll_prediv.hw
689		},
690		.num_parents = 1,
691	},
692};
693
694static struct clk_regmap s4_mpll2 = {
695	.data = &(struct clk_regmap_gate_data){
696		.offset = ANACTRL_MPLL_CTRL5,
697		.bit_idx = 31,
698	},
699	.hw.init = &(struct clk_init_data){
700		.name = "mpll2",
701		.ops = &clk_regmap_gate_ops,
702		.parent_hws = (const struct clk_hw *[]) { &s4_mpll2_div.hw },
703		.num_parents = 1,
704		.flags = CLK_SET_RATE_PARENT,
705	},
706};
707
708static const struct reg_sequence s4_mpll3_init_regs[] = {
709	{ .reg = ANACTRL_MPLL_CTRL8, .def = 0x40000033 }
710};
711
712static struct clk_regmap s4_mpll3_div = {
713	.data = &(struct meson_clk_mpll_data){
714		.sdm = {
715			.reg_off = ANACTRL_MPLL_CTRL7,
716			.shift   = 0,
717			.width   = 14,
718		},
719		.sdm_en = {
720			.reg_off = ANACTRL_MPLL_CTRL7,
721			.shift   = 30,
722			.width	 = 1,
723		},
724		.n2 = {
725			.reg_off = ANACTRL_MPLL_CTRL7,
726			.shift   = 20,
727			.width   = 9,
728		},
729		.ssen = {
730			.reg_off = ANACTRL_MPLL_CTRL7,
731			.shift   = 29,
732			.width	 = 1,
733		},
734		.init_regs = s4_mpll3_init_regs,
735		.init_count = ARRAY_SIZE(s4_mpll3_init_regs),
736	},
737	.hw.init = &(struct clk_init_data){
738		.name = "mpll3_div",
739		.ops = &meson_clk_mpll_ops,
740		.parent_hws = (const struct clk_hw *[]) {
741			&s4_mpll_prediv.hw
742		},
743		.num_parents = 1,
744	},
745};
746
747static struct clk_regmap s4_mpll3 = {
748	.data = &(struct clk_regmap_gate_data){
749		.offset = ANACTRL_MPLL_CTRL7,
750		.bit_idx = 31,
751	},
752	.hw.init = &(struct clk_init_data){
753		.name = "mpll3",
754		.ops = &clk_regmap_gate_ops,
755		.parent_hws = (const struct clk_hw *[]) { &s4_mpll3_div.hw },
756		.num_parents = 1,
757		.flags = CLK_SET_RATE_PARENT,
758	},
759};
760
761/* Array of all clocks provided by this provider */
762static struct clk_hw *s4_pll_hw_clks[] = {
763	[CLKID_FIXED_PLL_DCO]		= &s4_fixed_pll_dco.hw,
764	[CLKID_FIXED_PLL]		= &s4_fixed_pll.hw,
765	[CLKID_FCLK_DIV2_DIV]		= &s4_fclk_div2_div.hw,
766	[CLKID_FCLK_DIV2]		= &s4_fclk_div2.hw,
767	[CLKID_FCLK_DIV3_DIV]		= &s4_fclk_div3_div.hw,
768	[CLKID_FCLK_DIV3]		= &s4_fclk_div3.hw,
769	[CLKID_FCLK_DIV4_DIV]		= &s4_fclk_div4_div.hw,
770	[CLKID_FCLK_DIV4]		= &s4_fclk_div4.hw,
771	[CLKID_FCLK_DIV5_DIV]		= &s4_fclk_div5_div.hw,
772	[CLKID_FCLK_DIV5]		= &s4_fclk_div5.hw,
773	[CLKID_FCLK_DIV7_DIV]		= &s4_fclk_div7_div.hw,
774	[CLKID_FCLK_DIV7]		= &s4_fclk_div7.hw,
775	[CLKID_FCLK_DIV2P5_DIV]		= &s4_fclk_div2p5_div.hw,
776	[CLKID_FCLK_DIV2P5]		= &s4_fclk_div2p5.hw,
777	[CLKID_GP0_PLL_DCO]		= &s4_gp0_pll_dco.hw,
778	[CLKID_GP0_PLL]			= &s4_gp0_pll.hw,
779	[CLKID_HIFI_PLL_DCO]		= &s4_hifi_pll_dco.hw,
780	[CLKID_HIFI_PLL]		= &s4_hifi_pll.hw,
781	[CLKID_HDMI_PLL_DCO]		= &s4_hdmi_pll_dco.hw,
782	[CLKID_HDMI_PLL_OD]		= &s4_hdmi_pll_od.hw,
783	[CLKID_HDMI_PLL]		= &s4_hdmi_pll.hw,
784	[CLKID_MPLL_50M_DIV]		= &s4_mpll_50m_div.hw,
785	[CLKID_MPLL_50M]		= &s4_mpll_50m.hw,
786	[CLKID_MPLL_PREDIV]		= &s4_mpll_prediv.hw,
787	[CLKID_MPLL0_DIV]		= &s4_mpll0_div.hw,
788	[CLKID_MPLL0]			= &s4_mpll0.hw,
789	[CLKID_MPLL1_DIV]		= &s4_mpll1_div.hw,
790	[CLKID_MPLL1]			= &s4_mpll1.hw,
791	[CLKID_MPLL2_DIV]		= &s4_mpll2_div.hw,
792	[CLKID_MPLL2]			= &s4_mpll2.hw,
793	[CLKID_MPLL3_DIV]		= &s4_mpll3_div.hw,
794	[CLKID_MPLL3]			= &s4_mpll3.hw,
795};
796
797static const struct reg_sequence s4_pll_init_regs[] = {
798	{ .reg = ANACTRL_MPLL_CTRL0,	.def = 0x00000543 },
799};
800
801static const struct meson_clkc_data s4_pll_clkc_data = {
802	.hw_clks = {
803		.hws = s4_pll_hw_clks,
804		.num = ARRAY_SIZE(s4_pll_hw_clks),
805	},
806	.init_regs = s4_pll_init_regs,
807	.init_count = ARRAY_SIZE(s4_pll_init_regs),
808};
809
810static const struct of_device_id s4_pll_clkc_match_table[] = {
811	{
812		.compatible = "amlogic,s4-pll-clkc",
813		.data = &s4_pll_clkc_data,
814	},
815	{}
816};
817MODULE_DEVICE_TABLE(of, s4_pll_clkc_match_table);
818
819static struct platform_driver s4_pll_clkc_driver = {
820	.probe		= meson_clkc_mmio_probe,
821	.driver		= {
822		.name	= "s4-pll-clkc",
823		.of_match_table = s4_pll_clkc_match_table,
824	},
825};
826module_platform_driver(s4_pll_clkc_driver);
827
828MODULE_DESCRIPTION("Amlogic S4 PLL Clock Controller driver");
829MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
830MODULE_LICENSE("GPL");
831MODULE_IMPORT_NS("CLK_MESON");
~/ Read-only file preview.