brintos

brintos / linux-shallow public Read only

0
0
Text · 16.8 KiB · 32bd2ed Raw
749 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Amlogic C3 PLL Controller Driver4 *5 * Copyright (c) 2023 Amlogic, inc.6 * Author: Chuan Liu <chuan.liu@amlogic.com>7 */8 9#include <linux/clk-provider.h>10#include <linux/platform_device.h>11#include "clk-regmap.h"12#include "clk-pll.h"13#include "meson-clkc-utils.h"14#include <dt-bindings/clock/amlogic,c3-pll-clkc.h>15 16#define ANACTRL_FIXPLL_CTRL4			0x5017#define ANACTRL_GP0PLL_CTRL0			0x8018#define ANACTRL_GP0PLL_CTRL1			0x8419#define ANACTRL_GP0PLL_CTRL2			0x8820#define ANACTRL_GP0PLL_CTRL3			0x8c21#define ANACTRL_GP0PLL_CTRL4			0x9022#define ANACTRL_GP0PLL_CTRL5			0x9423#define ANACTRL_GP0PLL_CTRL6			0x9824#define ANACTRL_HIFIPLL_CTRL0			0x10025#define ANACTRL_HIFIPLL_CTRL1			0x10426#define ANACTRL_HIFIPLL_CTRL2			0x10827#define ANACTRL_HIFIPLL_CTRL3			0x10c28#define ANACTRL_HIFIPLL_CTRL4			0x11029#define ANACTRL_HIFIPLL_CTRL5			0x11430#define ANACTRL_HIFIPLL_CTRL6			0x11831#define ANACTRL_MPLL_CTRL0			0x18032#define ANACTRL_MPLL_CTRL1			0x18433#define ANACTRL_MPLL_CTRL2			0x18834#define ANACTRL_MPLL_CTRL3			0x18c35#define ANACTRL_MPLL_CTRL4			0x19036 37static struct clk_regmap fclk_50m_en = {38	.data = &(struct clk_regmap_gate_data) {39		.offset = ANACTRL_FIXPLL_CTRL4,40		.bit_idx = 0,41	},42	.hw.init = &(struct clk_init_data) {43		.name = "fclk_50m_en",44		.ops = &clk_regmap_gate_ro_ops,45		.parent_data = &(const struct clk_parent_data) {46			.fw_name = "fix"47		},48		.num_parents = 1,49	},50};51 52static struct clk_fixed_factor fclk_50m = {53	.mult = 1,54	.div = 40,55	.hw.init = &(struct clk_init_data) {56		.name = "fclk_50m",57		.ops = &clk_fixed_factor_ops,58		.parent_hws = (const struct clk_hw *[]) {59			&fclk_50m_en.hw60		},61		.num_parents = 1,62	},63};64 65static struct clk_fixed_factor fclk_div2_div = {66	.mult = 1,67	.div = 2,68	.hw.init = &(struct clk_init_data) {69		.name = "fclk_div2_div",70		.ops = &clk_fixed_factor_ops,71		.parent_data = &(const struct clk_parent_data) {72			.fw_name = "fix"73		},74		.num_parents = 1,75	},76};77 78static struct clk_regmap fclk_div2 = {79	.data = &(struct clk_regmap_gate_data) {80		.offset = ANACTRL_FIXPLL_CTRL4,81		.bit_idx = 24,82	},83	.hw.init = &(struct clk_init_data) {84		.name = "fclk_div2",85		.ops = &clk_regmap_gate_ro_ops,86		.parent_hws = (const struct clk_hw *[]) {87			&fclk_div2_div.hw88		},89		.num_parents = 1,90	},91};92 93static struct clk_fixed_factor fclk_div2p5_div = {94	.mult = 2,95	.div = 5,96	.hw.init = &(struct clk_init_data) {97		.name = "fclk_div2p5_div",98		.ops = &clk_fixed_factor_ops,99		.parent_data = &(const struct clk_parent_data) {100			.fw_name = "fix"101		},102		.num_parents = 1,103	},104};105 106static struct clk_regmap fclk_div2p5 = {107	.data = &(struct clk_regmap_gate_data) {108		.offset = ANACTRL_FIXPLL_CTRL4,109		.bit_idx = 4,110	},111	.hw.init = &(struct clk_init_data) {112		.name = "fclk_div2p5",113		.ops = &clk_regmap_gate_ro_ops,114		.parent_hws = (const struct clk_hw *[]) {115			&fclk_div2p5_div.hw116		},117		.num_parents = 1,118	},119};120 121static struct clk_fixed_factor fclk_div3_div = {122	.mult = 1,123	.div = 3,124	.hw.init = &(struct clk_init_data) {125		.name = "fclk_div3_div",126		.ops = &clk_fixed_factor_ops,127		.parent_data = &(const struct clk_parent_data) {128			.fw_name = "fix"129		},130		.num_parents = 1,131	},132};133 134static struct clk_regmap fclk_div3 = {135	.data = &(struct clk_regmap_gate_data) {136		.offset = ANACTRL_FIXPLL_CTRL4,137		.bit_idx = 20,138	},139	.hw.init = &(struct clk_init_data) {140		.name = "fclk_div3",141		.ops = &clk_regmap_gate_ro_ops,142		.parent_hws = (const struct clk_hw *[]) {143			&fclk_div3_div.hw144		},145		.num_parents = 1,146	},147};148 149static struct clk_fixed_factor fclk_div4_div = {150	.mult = 1,151	.div = 4,152	.hw.init = &(struct clk_init_data) {153		.name = "fclk_div4_div",154		.ops = &clk_fixed_factor_ops,155		.parent_data = &(const struct clk_parent_data) {156			.fw_name = "fix"157		},158		.num_parents = 1,159	},160};161 162static struct clk_regmap fclk_div4 = {163	.data = &(struct clk_regmap_gate_data) {164		.offset = ANACTRL_FIXPLL_CTRL4,165		.bit_idx = 21,166	},167	.hw.init = &(struct clk_init_data) {168		.name = "fclk_div4",169		.ops = &clk_regmap_gate_ro_ops,170		.parent_hws = (const struct clk_hw *[]) {171			&fclk_div4_div.hw172		},173		.num_parents = 1,174	},175};176 177static struct clk_fixed_factor fclk_div5_div = {178	.mult = 1,179	.div = 5,180	.hw.init = &(struct clk_init_data) {181		.name = "fclk_div5_div",182		.ops = &clk_fixed_factor_ops,183		.parent_data = &(const struct clk_parent_data) {184			.fw_name = "fix"185		},186		.num_parents = 1,187	},188};189 190static struct clk_regmap fclk_div5 = {191	.data = &(struct clk_regmap_gate_data) {192		.offset = ANACTRL_FIXPLL_CTRL4,193		.bit_idx = 22,194	},195	.hw.init = &(struct clk_init_data) {196		.name = "fclk_div5",197		.ops = &clk_regmap_gate_ro_ops,198		.parent_hws = (const struct clk_hw *[]) {199			&fclk_div5_div.hw200		},201		.num_parents = 1,202	},203};204 205static struct clk_fixed_factor fclk_div7_div = {206	.mult = 1,207	.div = 7,208	.hw.init = &(struct clk_init_data) {209		.name = "fclk_div7_div",210		.ops = &clk_fixed_factor_ops,211		.parent_data = &(const struct clk_parent_data) {212			.fw_name = "fix"213		},214		.num_parents = 1,215	},216};217 218static struct clk_regmap fclk_div7 = {219	.data = &(struct clk_regmap_gate_data) {220		.offset = ANACTRL_FIXPLL_CTRL4,221		.bit_idx = 23,222	},223	.hw.init = &(struct clk_init_data) {224		.name = "fclk_div7",225		.ops = &clk_regmap_gate_ro_ops,226		.parent_hws = (const struct clk_hw *[]) {227			&fclk_div7_div.hw228		},229		.num_parents = 1,230	},231};232 233static const struct reg_sequence c3_gp0_init_regs[] = {234	{ .reg = ANACTRL_GP0PLL_CTRL2,	.def = 0x0 },235	{ .reg = ANACTRL_GP0PLL_CTRL3,	.def = 0x48681c00 },236	{ .reg = ANACTRL_GP0PLL_CTRL4,  .def = 0x88770290 },237	{ .reg = ANACTRL_GP0PLL_CTRL5,  .def = 0x3927200a },238	{ .reg = ANACTRL_GP0PLL_CTRL6,	.def = 0x56540000 },239};240 241static const struct pll_mult_range c3_gp0_pll_mult_range = {242	.min = 125,243	.max = 250,244};245 246static struct clk_regmap gp0_pll_dco = {247	.data = &(struct meson_clk_pll_data) {248		.en = {249			.reg_off = ANACTRL_GP0PLL_CTRL0,250			.shift   = 28,251			.width   = 1,252		},253		.m = {254			.reg_off = ANACTRL_GP0PLL_CTRL0,255			.shift   = 0,256			.width   = 9,257		},258		.frac = {259			.reg_off = ANACTRL_GP0PLL_CTRL1,260			.shift   = 0,261			.width   = 19,262		},263		.n = {264			.reg_off = ANACTRL_GP0PLL_CTRL0,265			.shift   = 10,266			.width   = 5,267		},268		.l = {269			.reg_off = ANACTRL_GP0PLL_CTRL0,270			.shift   = 31,271			.width   = 1,272		},273		.rst = {274			.reg_off = ANACTRL_GP0PLL_CTRL0,275			.shift   = 29,276			.width   = 1,277		},278		.range = &c3_gp0_pll_mult_range,279		.init_regs = c3_gp0_init_regs,280		.init_count = ARRAY_SIZE(c3_gp0_init_regs),281	},282	.hw.init = &(struct clk_init_data) {283		.name = "gp0_pll_dco",284		.ops = &meson_clk_pll_ops,285		.parent_data = &(const struct clk_parent_data) {286			.fw_name = "top",287		},288		.num_parents = 1,289	},290};291 292/* The maximum frequency divider supports is 32, not 128(2^7) */293static const struct clk_div_table c3_gp0_pll_od_table[] = {294	{ 0,  1 },295	{ 1,  2 },296	{ 2,  4 },297	{ 3,  8 },298	{ 4, 16 },299	{ 5, 32 },300	{ /* sentinel */ }301};302 303static struct clk_regmap gp0_pll = {304	.data = &(struct clk_regmap_div_data) {305		.offset = ANACTRL_GP0PLL_CTRL0,306		.shift = 16,307		.width = 3,308		.table = c3_gp0_pll_od_table,309	},310	.hw.init = &(struct clk_init_data) {311		.name = "gp0_pll",312		.ops = &clk_regmap_divider_ops,313		.parent_hws = (const struct clk_hw *[]) {314			&gp0_pll_dco.hw315		},316		.num_parents = 1,317		.flags = CLK_SET_RATE_PARENT,318	},319};320 321static const struct reg_sequence c3_hifi_init_regs[] = {322	{ .reg = ANACTRL_HIFIPLL_CTRL2,	.def = 0x0 },323	{ .reg = ANACTRL_HIFIPLL_CTRL3,	.def = 0x6a285c00 },324	{ .reg = ANACTRL_HIFIPLL_CTRL4, .def = 0x65771290 },325	{ .reg = ANACTRL_HIFIPLL_CTRL5, .def = 0x3927200a },326	{ .reg = ANACTRL_HIFIPLL_CTRL6,	.def = 0x56540000 },327};328 329static struct clk_regmap hifi_pll_dco = {330	.data = &(struct meson_clk_pll_data) {331		.en = {332			.reg_off = ANACTRL_HIFIPLL_CTRL0,333			.shift   = 28,334			.width   = 1,335		},336		.m = {337			.reg_off = ANACTRL_HIFIPLL_CTRL0,338			.shift   = 0,339			.width   = 8,340		},341		.frac = {342			.reg_off = ANACTRL_HIFIPLL_CTRL1,343			.shift   = 0,344			.width   = 19,345		},346		.n = {347			.reg_off = ANACTRL_HIFIPLL_CTRL0,348			.shift   = 10,349			.width   = 5,350		},351		.l = {352			.reg_off = ANACTRL_HIFIPLL_CTRL0,353			.shift   = 31,354			.width   = 1,355		},356		.rst = {357			.reg_off = ANACTRL_HIFIPLL_CTRL0,358			.shift   = 29,359			.width   = 1,360		},361		.range = &c3_gp0_pll_mult_range,362		.init_regs = c3_hifi_init_regs,363		.init_count = ARRAY_SIZE(c3_hifi_init_regs),364	},365	.hw.init = &(struct clk_init_data) {366		.name = "hifi_pll_dco",367		.ops = &meson_clk_pll_ops,368		.parent_data = &(const struct clk_parent_data) {369			.fw_name = "top",370		},371		.num_parents = 1,372	},373};374 375static struct clk_regmap hifi_pll = {376	.data = &(struct clk_regmap_div_data) {377		.offset = ANACTRL_HIFIPLL_CTRL0,378		.shift = 16,379		.width = 2,380		.flags = CLK_DIVIDER_POWER_OF_TWO,381	},382	.hw.init = &(struct clk_init_data) {383		.name = "hifi_pll",384		.ops = &clk_regmap_divider_ops,385		.parent_hws = (const struct clk_hw *[]) {386			&hifi_pll_dco.hw387		},388		.num_parents = 1,389		.flags = CLK_SET_RATE_PARENT,390	},391};392 393static const struct reg_sequence c3_mclk_init_regs[] = {394	{ .reg = ANACTRL_MPLL_CTRL1,	.def = 0x1420500f },395	{ .reg = ANACTRL_MPLL_CTRL2,	.def = 0x00023041 },396	{ .reg = ANACTRL_MPLL_CTRL3,	.def = 0x18180000 },397	{ .reg = ANACTRL_MPLL_CTRL2,	.def = 0x00023001 }398};399 400static const struct pll_mult_range c3_mclk_pll_mult_range = {401	.min = 67,402	.max = 133,403};404 405static struct clk_regmap mclk_pll_dco = {406	.data = &(struct meson_clk_pll_data) {407		.en = {408			.reg_off = ANACTRL_MPLL_CTRL0,409			.shift   = 28,410			.width   = 1,411		},412		.m = {413			.reg_off = ANACTRL_MPLL_CTRL0,414			.shift   = 0,415			.width   = 8,416		},417		.n = {418			.reg_off = ANACTRL_MPLL_CTRL0,419			.shift   = 16,420			.width   = 5,421		},422		.l = {423			.reg_off = ANACTRL_MPLL_CTRL0,424			.shift   = 31,425			.width   = 1,426		},427		.rst = {428			.reg_off = ANACTRL_MPLL_CTRL0,429			.shift   = 29,430			.width   = 1,431		},432		.range = &c3_mclk_pll_mult_range,433		.init_regs = c3_mclk_init_regs,434		.init_count = ARRAY_SIZE(c3_mclk_init_regs),435	},436	.hw.init = &(struct clk_init_data) {437		.name = "mclk_pll_dco",438		.ops = &meson_clk_pll_ops,439		.parent_data = &(const struct clk_parent_data) {440			.fw_name = "mclk",441		},442		.num_parents = 1,443	},444};445 446static const struct clk_div_table c3_mpll_od_table[] = {447	{ 0,  1 },448	{ 1,  2 },449	{ 2,  4 },450	{ 3,  8 },451	{ 4, 16 },452	{ /* sentinel */ }453};454 455static struct clk_regmap mclk_pll_od = {456	.data = &(struct clk_regmap_div_data) {457		.offset = ANACTRL_MPLL_CTRL0,458		.shift = 12,459		.width = 3,460		.table = c3_mpll_od_table,461	},462	.hw.init = &(struct clk_init_data) {463		.name = "mclk_pll_od",464		.ops = &clk_regmap_divider_ops,465		.parent_hws = (const struct clk_hw *[]) {466			&mclk_pll_dco.hw },467		.num_parents = 1,468		.flags = CLK_SET_RATE_PARENT,469	},470};471 472/* both value 0 and 1 gives divide the input rate by one */473static struct clk_regmap mclk_pll = {474	.data = &(struct clk_regmap_div_data) {475		.offset = ANACTRL_MPLL_CTRL4,476		.shift = 16,477		.width = 5,478		.flags = CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,479	},480	.hw.init = &(struct clk_init_data) {481		.name = "mclk_pll",482		.ops = &clk_regmap_divider_ops,483		.parent_hws = (const struct clk_hw *[]) {484			&mclk_pll_od.hw485		},486		.num_parents = 1,487		.flags = CLK_SET_RATE_PARENT,488	},489};490 491static const struct clk_parent_data mclk_parent[] = {492	{ .hw = &mclk_pll.hw },493	{ .fw_name = "mclk" },494	{ .hw = &fclk_50m.hw }495};496 497static struct clk_regmap mclk0_sel = {498	.data = &(struct clk_regmap_mux_data) {499		.offset = ANACTRL_MPLL_CTRL4,500		.mask = 0x3,501		.shift = 4,502	},503	.hw.init = &(struct clk_init_data) {504		.name = "mclk0_sel",505		.ops = &clk_regmap_mux_ops,506		.parent_data = mclk_parent,507		.num_parents = ARRAY_SIZE(mclk_parent),508	},509};510 511static struct clk_regmap mclk0_div_en = {512	.data = &(struct clk_regmap_gate_data) {513		.offset = ANACTRL_MPLL_CTRL4,514		.bit_idx = 1,515	},516	.hw.init = &(struct clk_init_data) {517		.name = "mclk0_div_en",518		.ops = &clk_regmap_gate_ops,519		.parent_hws = (const struct clk_hw *[]) {520			&mclk0_sel.hw521		},522		.num_parents = 1,523		.flags = CLK_SET_RATE_PARENT,524	},525};526 527static struct clk_regmap mclk0_div = {528	.data = &(struct clk_regmap_div_data) {529		.offset = ANACTRL_MPLL_CTRL4,530		.shift = 2,531		.width = 1,532	},533	.hw.init = &(struct clk_init_data) {534		.name = "mclk0_div",535		.ops = &clk_regmap_divider_ops,536		.parent_hws = (const struct clk_hw *[]) {537			&mclk0_div_en.hw538		},539		.num_parents = 1,540		.flags = CLK_SET_RATE_PARENT,541	},542};543 544static struct clk_regmap mclk0 = {545	.data = &(struct clk_regmap_gate_data) {546		.offset = ANACTRL_MPLL_CTRL4,547		.bit_idx = 0,548	},549	.hw.init = &(struct clk_init_data) {550		.name = "mclk0",551		.ops = &clk_regmap_gate_ops,552		.parent_hws = (const struct clk_hw *[]) {553			&mclk0_div.hw554		},555		.num_parents = 1,556		.flags = CLK_SET_RATE_PARENT,557	},558};559 560static struct clk_regmap mclk1_sel = {561	.data = &(struct clk_regmap_mux_data) {562		.offset = ANACTRL_MPLL_CTRL4,563		.mask = 0x3,564		.shift = 12,565	},566	.hw.init = &(struct clk_init_data) {567		.name = "mclk1_sel",568		.ops = &clk_regmap_mux_ops,569		.parent_data = mclk_parent,570		.num_parents = ARRAY_SIZE(mclk_parent),571	},572};573 574static struct clk_regmap mclk1_div_en = {575	.data = &(struct clk_regmap_gate_data) {576		.offset = ANACTRL_MPLL_CTRL4,577		.bit_idx = 9,578	},579	.hw.init = &(struct clk_init_data) {580		.name = "mclk1_div_en",581		.ops = &clk_regmap_gate_ops,582		.parent_hws = (const struct clk_hw *[]) {583			&mclk1_sel.hw584		},585		.num_parents = 1,586		.flags = CLK_SET_RATE_PARENT,587	},588};589 590static struct clk_regmap mclk1_div = {591	.data = &(struct clk_regmap_div_data) {592		.offset = ANACTRL_MPLL_CTRL4,593		.shift = 10,594		.width = 1,595	},596	.hw.init = &(struct clk_init_data) {597		.name = "mclk1_div",598		.ops = &clk_regmap_divider_ops,599		.parent_hws = (const struct clk_hw *[]) {600			&mclk1_div_en.hw601		},602		.num_parents = 1,603		.flags = CLK_SET_RATE_PARENT,604	},605};606 607static struct clk_regmap mclk1 = {608	.data = &(struct clk_regmap_gate_data) {609		.offset = ANACTRL_MPLL_CTRL4,610		.bit_idx = 8,611	},612	.hw.init = &(struct clk_init_data) {613		.name = "mclk1",614		.ops = &clk_regmap_gate_ops,615		.parent_hws = (const struct clk_hw *[]) {616			&mclk1_div.hw617		},618		.num_parents = 1,619		.flags = CLK_SET_RATE_PARENT,620	},621};622 623static struct clk_hw *c3_pll_hw_clks[] = {624	[CLKID_FCLK_50M_EN]	= &fclk_50m_en.hw,625	[CLKID_FCLK_50M]	= &fclk_50m.hw,626	[CLKID_FCLK_DIV2_DIV]	= &fclk_div2_div.hw,627	[CLKID_FCLK_DIV2]	= &fclk_div2.hw,628	[CLKID_FCLK_DIV2P5_DIV]	= &fclk_div2p5_div.hw,629	[CLKID_FCLK_DIV2P5]	= &fclk_div2p5.hw,630	[CLKID_FCLK_DIV3_DIV]	= &fclk_div3_div.hw,631	[CLKID_FCLK_DIV3]	= &fclk_div3.hw,632	[CLKID_FCLK_DIV4_DIV]	= &fclk_div4_div.hw,633	[CLKID_FCLK_DIV4]	= &fclk_div4.hw,634	[CLKID_FCLK_DIV5_DIV]	= &fclk_div5_div.hw,635	[CLKID_FCLK_DIV5]	= &fclk_div5.hw,636	[CLKID_FCLK_DIV7_DIV]	= &fclk_div7_div.hw,637	[CLKID_FCLK_DIV7]	= &fclk_div7.hw,638	[CLKID_GP0_PLL_DCO]	= &gp0_pll_dco.hw,639	[CLKID_GP0_PLL]		= &gp0_pll.hw,640	[CLKID_HIFI_PLL_DCO]	= &hifi_pll_dco.hw,641	[CLKID_HIFI_PLL]	= &hifi_pll.hw,642	[CLKID_MCLK_PLL_DCO]	= &mclk_pll_dco.hw,643	[CLKID_MCLK_PLL_OD]	= &mclk_pll_od.hw,644	[CLKID_MCLK_PLL]	= &mclk_pll.hw,645	[CLKID_MCLK0_SEL]	= &mclk0_sel.hw,646	[CLKID_MCLK0_SEL_EN]	= &mclk0_div_en.hw,647	[CLKID_MCLK0_DIV]	= &mclk0_div.hw,648	[CLKID_MCLK0]		= &mclk0.hw,649	[CLKID_MCLK1_SEL]	= &mclk1_sel.hw,650	[CLKID_MCLK1_SEL_EN]	= &mclk1_div_en.hw,651	[CLKID_MCLK1_DIV]	= &mclk1_div.hw,652	[CLKID_MCLK1]		= &mclk1.hw653};654 655/* Convenience table to populate regmap in .probe */656static struct clk_regmap *const c3_pll_clk_regmaps[] = {657	&fclk_50m_en,658	&fclk_div2,659	&fclk_div2p5,660	&fclk_div3,661	&fclk_div4,662	&fclk_div5,663	&fclk_div7,664	&gp0_pll_dco,665	&gp0_pll,666	&hifi_pll_dco,667	&hifi_pll,668	&mclk_pll_dco,669	&mclk_pll_od,670	&mclk_pll,671	&mclk0_sel,672	&mclk0_div_en,673	&mclk0_div,674	&mclk0,675	&mclk1_sel,676	&mclk1_div_en,677	&mclk1_div,678	&mclk1,679};680 681static const struct regmap_config clkc_regmap_config = {682	.reg_bits       = 32,683	.val_bits       = 32,684	.reg_stride     = 4,685	.max_register   = ANACTRL_MPLL_CTRL4,686};687 688static struct meson_clk_hw_data c3_pll_clks = {689	.hws = c3_pll_hw_clks,690	.num = ARRAY_SIZE(c3_pll_hw_clks),691};692 693static int c3_pll_probe(struct platform_device *pdev)694{695	struct device *dev = &pdev->dev;696	struct regmap *regmap;697	void __iomem *base;698	int clkid, ret, i;699 700	base = devm_platform_ioremap_resource(pdev, 0);701	if (IS_ERR(base))702		return PTR_ERR(base);703 704	regmap = devm_regmap_init_mmio(dev, base, &clkc_regmap_config);705	if (IS_ERR(regmap))706		return PTR_ERR(regmap);707 708	/* Populate regmap for the regmap backed clocks */709	for (i = 0; i < ARRAY_SIZE(c3_pll_clk_regmaps); i++)710		c3_pll_clk_regmaps[i]->map = regmap;711 712	for (clkid = 0; clkid < c3_pll_clks.num; clkid++) {713		/* array might be sparse */714		if (!c3_pll_clks.hws[clkid])715			continue;716 717		ret = devm_clk_hw_register(dev, c3_pll_clks.hws[clkid]);718		if (ret) {719			dev_err(dev, "Clock registration failed\n");720			return ret;721		}722	}723 724	return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get,725					   &c3_pll_clks);726}727 728static const struct of_device_id c3_pll_clkc_match_table[] = {729	{730		.compatible = "amlogic,c3-pll-clkc",731	},732	{}733};734MODULE_DEVICE_TABLE(of, c3_pll_clkc_match_table);735 736static struct platform_driver c3_pll_driver = {737	.probe		= c3_pll_probe,738	.driver		= {739		.name	= "c3-pll-clkc",740		.of_match_table = c3_pll_clkc_match_table,741	},742};743module_platform_driver(c3_pll_driver);744 745MODULE_DESCRIPTION("Amlogic C3 PLL Clock Controller driver");746MODULE_AUTHOR("Chuan Liu <chuan.liu@amlogic.com>");747MODULE_LICENSE("GPL");748MODULE_IMPORT_NS(CLK_MESON);749