brintos

brintos / linux-shallow public Read only

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