brintos

brintos / linux-shallow public Read only

0
0
Text · 27.6 KiB · 17e32ae Raw
1090 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (C) 2023 Jisheng Zhang <jszhang@kernel.org>4 * Copyright (C) 2023 Vivo Communication Technology Co. Ltd.5 *  Authors: Yangtao Li <frank.li@vivo.com>6 */7 8#include <dt-bindings/clock/thead,th1520-clk-ap.h>9#include <linux/bitfield.h>10#include <linux/clk-provider.h>11#include <linux/device.h>12#include <linux/module.h>13#include <linux/platform_device.h>14#include <linux/regmap.h>15 16#define TH1520_PLL_POSTDIV2	GENMASK(26, 24)17#define TH1520_PLL_POSTDIV1	GENMASK(22, 20)18#define TH1520_PLL_FBDIV	GENMASK(19, 8)19#define TH1520_PLL_REFDIV	GENMASK(5, 0)20#define TH1520_PLL_BYPASS	BIT(30)21#define TH1520_PLL_DSMPD	BIT(24)22#define TH1520_PLL_FRAC		GENMASK(23, 0)23#define TH1520_PLL_FRAC_BITS    2424 25struct ccu_internal {26	u8	shift;27	u8	width;28};29 30struct ccu_div_internal {31	u8	shift;32	u8	width;33	u32	flags;34};35 36struct ccu_common {37	int		clkid;38	struct regmap	*map;39	u16		cfg0;40	u16		cfg1;41	struct clk_hw	hw;42};43 44struct ccu_mux {45	struct ccu_internal	mux;46	struct ccu_common	common;47};48 49struct ccu_gate {50	u32			enable;51	struct ccu_common	common;52};53 54struct ccu_div {55	u32			enable;56	struct ccu_div_internal	div;57	struct ccu_internal	mux;58	struct ccu_common	common;59};60 61struct ccu_pll {62	struct ccu_common	common;63};64 65#define TH_CCU_ARG(_shift, _width)					\66	{								\67		.shift	= _shift,					\68		.width	= _width,					\69	}70 71#define TH_CCU_DIV_FLAGS(_shift, _width, _flags)			\72	{								\73		.shift	= _shift,					\74		.width	= _width,					\75		.flags	= _flags,					\76	}77 78#define CCU_GATE(_clkid, _struct, _name, _parent, _reg, _gate, _flags)	\79	struct ccu_gate _struct = {					\80		.enable	= _gate,					\81		.common	= {						\82			.clkid		= _clkid,			\83			.cfg0		= _reg,				\84			.hw.init	= CLK_HW_INIT_PARENTS_DATA(	\85						_name,			\86						_parent,		\87						&clk_gate_ops,		\88						_flags),		\89		}							\90	}91 92static inline struct ccu_common *hw_to_ccu_common(struct clk_hw *hw)93{94	return container_of(hw, struct ccu_common, hw);95}96 97static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw)98{99	struct ccu_common *common = hw_to_ccu_common(hw);100 101	return container_of(common, struct ccu_mux, common);102}103 104static inline struct ccu_pll *hw_to_ccu_pll(struct clk_hw *hw)105{106	struct ccu_common *common = hw_to_ccu_common(hw);107 108	return container_of(common, struct ccu_pll, common);109}110 111static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw)112{113	struct ccu_common *common = hw_to_ccu_common(hw);114 115	return container_of(common, struct ccu_div, common);116}117 118static inline struct ccu_gate *hw_to_ccu_gate(struct clk_hw *hw)119{120	struct ccu_common *common = hw_to_ccu_common(hw);121 122	return container_of(common, struct ccu_gate, common);123}124 125static u8 ccu_get_parent_helper(struct ccu_common *common,126				struct ccu_internal *mux)127{128	unsigned int val;129	u8 parent;130 131	regmap_read(common->map, common->cfg0, &val);132	parent = val >> mux->shift;133	parent &= GENMASK(mux->width - 1, 0);134 135	return parent;136}137 138static int ccu_set_parent_helper(struct ccu_common *common,139				 struct ccu_internal *mux,140				 u8 index)141{142	return regmap_update_bits(common->map, common->cfg0,143			GENMASK(mux->width - 1, 0) << mux->shift,144			index << mux->shift);145}146 147static void ccu_disable_helper(struct ccu_common *common, u32 gate)148{149	if (!gate)150		return;151	regmap_update_bits(common->map, common->cfg0,152			   gate, ~gate);153}154 155static int ccu_enable_helper(struct ccu_common *common, u32 gate)156{157	unsigned int val;158	int ret;159 160	if (!gate)161		return 0;162 163	ret = regmap_update_bits(common->map, common->cfg0, gate, gate);164	regmap_read(common->map, common->cfg0, &val);165	return ret;166}167 168static int ccu_is_enabled_helper(struct ccu_common *common, u32 gate)169{170	unsigned int val;171 172	if (!gate)173		return true;174 175	regmap_read(common->map, common->cfg0, &val);176	return val & gate;177}178 179static unsigned long ccu_div_recalc_rate(struct clk_hw *hw,180					 unsigned long parent_rate)181{182	struct ccu_div *cd = hw_to_ccu_div(hw);183	unsigned long rate;184	unsigned int val;185 186	regmap_read(cd->common.map, cd->common.cfg0, &val);187	val = val >> cd->div.shift;188	val &= GENMASK(cd->div.width - 1, 0);189	rate = divider_recalc_rate(hw, parent_rate, val, NULL,190				   cd->div.flags, cd->div.width);191 192	return rate;193}194 195static u8 ccu_div_get_parent(struct clk_hw *hw)196{197	struct ccu_div *cd = hw_to_ccu_div(hw);198 199	return ccu_get_parent_helper(&cd->common, &cd->mux);200}201 202static int ccu_div_set_parent(struct clk_hw *hw, u8 index)203{204	struct ccu_div *cd = hw_to_ccu_div(hw);205 206	return ccu_set_parent_helper(&cd->common, &cd->mux, index);207}208 209static void ccu_div_disable(struct clk_hw *hw)210{211	struct ccu_div *cd = hw_to_ccu_div(hw);212 213	ccu_disable_helper(&cd->common, cd->enable);214}215 216static int ccu_div_enable(struct clk_hw *hw)217{218	struct ccu_div *cd = hw_to_ccu_div(hw);219 220	return ccu_enable_helper(&cd->common, cd->enable);221}222 223static int ccu_div_is_enabled(struct clk_hw *hw)224{225	struct ccu_div *cd = hw_to_ccu_div(hw);226 227	return ccu_is_enabled_helper(&cd->common, cd->enable);228}229 230static const struct clk_ops ccu_div_ops = {231	.disable	= ccu_div_disable,232	.enable		= ccu_div_enable,233	.is_enabled	= ccu_div_is_enabled,234	.get_parent	= ccu_div_get_parent,235	.set_parent	= ccu_div_set_parent,236	.recalc_rate	= ccu_div_recalc_rate,237	.determine_rate	= clk_hw_determine_rate_no_reparent,238};239 240static unsigned long th1520_pll_vco_recalc_rate(struct clk_hw *hw,241						unsigned long parent_rate)242{243	struct ccu_pll *pll = hw_to_ccu_pll(hw);244	unsigned long div, mul, frac;245	unsigned int cfg0, cfg1;246	u64 rate = parent_rate;247 248	regmap_read(pll->common.map, pll->common.cfg0, &cfg0);249	regmap_read(pll->common.map, pll->common.cfg1, &cfg1);250 251	mul = FIELD_GET(TH1520_PLL_FBDIV, cfg0);252	div = FIELD_GET(TH1520_PLL_REFDIV, cfg0);253	if (!(cfg1 & TH1520_PLL_DSMPD)) {254		mul <<= TH1520_PLL_FRAC_BITS;255		frac = FIELD_GET(TH1520_PLL_FRAC, cfg1);256		mul += frac;257		div <<= TH1520_PLL_FRAC_BITS;258	}259	rate = parent_rate * mul;260	rate = rate / div;261	return rate;262}263 264static unsigned long th1520_pll_postdiv_recalc_rate(struct clk_hw *hw,265						    unsigned long parent_rate)266{267	struct ccu_pll *pll = hw_to_ccu_pll(hw);268	unsigned long div, rate = parent_rate;269	unsigned int cfg0, cfg1;270 271	regmap_read(pll->common.map, pll->common.cfg0, &cfg0);272	regmap_read(pll->common.map, pll->common.cfg1, &cfg1);273 274	if (cfg1 & TH1520_PLL_BYPASS)275		return rate;276 277	div = FIELD_GET(TH1520_PLL_POSTDIV1, cfg0) *278	      FIELD_GET(TH1520_PLL_POSTDIV2, cfg0);279 280	rate = rate / div;281 282	return rate;283}284 285static unsigned long ccu_pll_recalc_rate(struct clk_hw *hw,286					 unsigned long parent_rate)287{288	unsigned long rate = parent_rate;289 290	rate = th1520_pll_vco_recalc_rate(hw, rate);291	rate = th1520_pll_postdiv_recalc_rate(hw, rate);292 293	return rate;294}295 296static const struct clk_ops clk_pll_ops = {297	.recalc_rate	= ccu_pll_recalc_rate,298};299 300static const struct clk_parent_data osc_24m_clk[] = {301	{ .index = 0 }302};303 304static struct ccu_pll cpu_pll0_clk = {305	.common		= {306		.clkid		= CLK_CPU_PLL0,307		.cfg0		= 0x000,308		.cfg1		= 0x004,309		.hw.init	= CLK_HW_INIT_PARENTS_DATA("cpu-pll0",310					      osc_24m_clk,311					      &clk_pll_ops,312					      0),313	},314};315 316static struct ccu_pll cpu_pll1_clk = {317	.common		= {318		.clkid		= CLK_CPU_PLL1,319		.cfg0		= 0x010,320		.cfg1		= 0x014,321		.hw.init	= CLK_HW_INIT_PARENTS_DATA("cpu-pll1",322					      osc_24m_clk,323					      &clk_pll_ops,324					      0),325	},326};327 328static struct ccu_pll gmac_pll_clk = {329	.common		= {330		.clkid		= CLK_GMAC_PLL,331		.cfg0		= 0x020,332		.cfg1		= 0x024,333		.hw.init	= CLK_HW_INIT_PARENTS_DATA("gmac-pll",334					      osc_24m_clk,335					      &clk_pll_ops,336					      0),337	},338};339 340static const struct clk_hw *gmac_pll_clk_parent[] = {341	&gmac_pll_clk.common.hw342};343 344static const struct clk_parent_data gmac_pll_clk_pd[] = {345	{ .hw = &gmac_pll_clk.common.hw }346};347 348static struct ccu_pll video_pll_clk = {349	.common		= {350		.clkid		= CLK_VIDEO_PLL,351		.cfg0		= 0x030,352		.cfg1		= 0x034,353		.hw.init	= CLK_HW_INIT_PARENTS_DATA("video-pll",354					      osc_24m_clk,355					      &clk_pll_ops,356					      0),357	},358};359 360static const struct clk_hw *video_pll_clk_parent[] = {361	&video_pll_clk.common.hw362};363 364static const struct clk_parent_data video_pll_clk_pd[] = {365	{ .hw = &video_pll_clk.common.hw }366};367 368static struct ccu_pll dpu0_pll_clk = {369	.common		= {370		.clkid		= CLK_DPU0_PLL,371		.cfg0		= 0x040,372		.cfg1		= 0x044,373		.hw.init	= CLK_HW_INIT_PARENTS_DATA("dpu0-pll",374					      osc_24m_clk,375					      &clk_pll_ops,376					      0),377	},378};379 380static const struct clk_hw *dpu0_pll_clk_parent[] = {381	&dpu0_pll_clk.common.hw382};383 384static struct ccu_pll dpu1_pll_clk = {385	.common		= {386		.clkid		= CLK_DPU1_PLL,387		.cfg0		= 0x050,388		.cfg1		= 0x054,389		.hw.init	= CLK_HW_INIT_PARENTS_DATA("dpu1-pll",390					      osc_24m_clk,391					      &clk_pll_ops,392					      0),393	},394};395 396static const struct clk_hw *dpu1_pll_clk_parent[] = {397	&dpu1_pll_clk.common.hw398};399 400static struct ccu_pll tee_pll_clk = {401	.common		= {402		.clkid		= CLK_TEE_PLL,403		.cfg0		= 0x060,404		.cfg1		= 0x064,405		.hw.init	= CLK_HW_INIT_PARENTS_DATA("tee-pll",406					      osc_24m_clk,407					      &clk_pll_ops,408					      0),409	},410};411 412static const struct clk_parent_data c910_i0_parents[] = {413	{ .hw = &cpu_pll0_clk.common.hw },414	{ .index = 0 }415};416 417static struct ccu_mux c910_i0_clk = {418	.mux	= TH_CCU_ARG(1, 1),419	.common	= {420		.clkid		= CLK_C910_I0,421		.cfg0		= 0x100,422		.hw.init	= CLK_HW_INIT_PARENTS_DATA("c910-i0",423					      c910_i0_parents,424					      &clk_mux_ops,425					      0),426	}427};428 429static const struct clk_parent_data c910_parents[] = {430	{ .hw = &c910_i0_clk.common.hw },431	{ .hw = &cpu_pll1_clk.common.hw }432};433 434static struct ccu_mux c910_clk = {435	.mux	= TH_CCU_ARG(0, 1),436	.common	= {437		.clkid		= CLK_C910,438		.cfg0		= 0x100,439		.hw.init	= CLK_HW_INIT_PARENTS_DATA("c910",440					      c910_parents,441					      &clk_mux_ops,442					      0),443	}444};445 446static const struct clk_parent_data ahb2_cpusys_parents[] = {447	{ .hw = &gmac_pll_clk.common.hw },448	{ .index = 0 }449};450 451static struct ccu_div ahb2_cpusys_hclk = {452	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),453	.mux		= TH_CCU_ARG(5, 1),454	.common		= {455		.clkid          = CLK_AHB2_CPUSYS_HCLK,456		.cfg0		= 0x120,457		.hw.init	= CLK_HW_INIT_PARENTS_DATA("ahb2-cpusys-hclk",458						      ahb2_cpusys_parents,459						      &ccu_div_ops,460						      0),461	},462};463 464static const struct clk_parent_data ahb2_cpusys_hclk_pd[] = {465	{ .hw = &ahb2_cpusys_hclk.common.hw }466};467 468static const struct clk_hw *ahb2_cpusys_hclk_parent[] = {469	&ahb2_cpusys_hclk.common.hw,470};471 472static struct ccu_div apb3_cpusys_pclk = {473	.div		= TH_CCU_ARG(0, 3),474	.common		= {475		.clkid          = CLK_APB3_CPUSYS_PCLK,476		.cfg0		= 0x130,477		.hw.init	= CLK_HW_INIT_PARENTS_HW("apb3-cpusys-pclk",478							   ahb2_cpusys_hclk_parent,479							   &ccu_div_ops,480							   0),481	},482};483 484static const struct clk_parent_data apb3_cpusys_pclk_pd[] = {485	{ .hw = &apb3_cpusys_pclk.common.hw }486};487 488static struct ccu_div axi4_cpusys2_aclk = {489	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),490	.common		= {491		.clkid          = CLK_AXI4_CPUSYS2_ACLK,492		.cfg0		= 0x134,493		.hw.init	= CLK_HW_INIT_PARENTS_HW("axi4-cpusys2-aclk",494					      gmac_pll_clk_parent,495					      &ccu_div_ops,496					      0),497	},498};499 500static const struct clk_parent_data axi4_cpusys2_aclk_pd[] = {501	{ .hw = &axi4_cpusys2_aclk.common.hw }502};503 504static const struct clk_parent_data axi_parents[] = {505	{ .hw = &video_pll_clk.common.hw },506	{ .index = 0 }507};508 509static struct ccu_div axi_aclk = {510	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),511	.mux		= TH_CCU_ARG(5, 1),512	.common		= {513		.clkid          = CLK_AXI_ACLK,514		.cfg0		= 0x138,515		.hw.init	= CLK_HW_INIT_PARENTS_DATA("axi-aclk",516						      axi_parents,517						      &ccu_div_ops,518						      0),519	},520};521 522static const struct clk_parent_data axi_aclk_pd[] = {523	{ .hw = &axi_aclk.common.hw }524};525 526static const struct clk_parent_data perisys_ahb_hclk_parents[] = {527	{ .hw = &gmac_pll_clk.common.hw },528	{ .index = 0 },529};530 531static struct ccu_div perisys_ahb_hclk = {532	.enable		= BIT(6),533	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),534	.mux		= TH_CCU_ARG(5, 1),535	.common		= {536		.clkid          = CLK_PERI_AHB_HCLK,537		.cfg0		= 0x140,538		.hw.init	= CLK_HW_INIT_PARENTS_DATA("perisys-ahb-hclk",539						      perisys_ahb_hclk_parents,540						      &ccu_div_ops,541						      0),542	},543};544 545static const struct clk_parent_data perisys_ahb_hclk_pd[] = {546	{ .hw = &perisys_ahb_hclk.common.hw }547};548 549static const struct clk_hw *perisys_ahb_hclk_parent[] = {550	&perisys_ahb_hclk.common.hw551};552 553static struct ccu_div perisys_apb_pclk = {554	.div		= TH_CCU_ARG(0, 3),555	.common		= {556		.clkid          = CLK_PERI_APB_PCLK,557		.cfg0		= 0x150,558		.hw.init	= CLK_HW_INIT_PARENTS_HW("perisys-apb-pclk",559					      perisys_ahb_hclk_parent,560					      &ccu_div_ops,561					      0),562	},563};564 565static const struct clk_parent_data perisys_apb_pclk_pd[] = {566	{ .hw = &perisys_apb_pclk.common.hw }567};568 569static struct ccu_div peri2sys_apb_pclk = {570	.div		= TH_CCU_DIV_FLAGS(4, 3, CLK_DIVIDER_ONE_BASED),571	.common		= {572		.clkid          = CLK_PERI2APB_PCLK,573		.cfg0		= 0x150,574		.hw.init	= CLK_HW_INIT_PARENTS_HW("peri2sys-apb-pclk",575					      gmac_pll_clk_parent,576					      &ccu_div_ops,577					      0),578	},579};580 581static const struct clk_parent_data peri2sys_apb_pclk_pd[] = {582	{ .hw = &peri2sys_apb_pclk.common.hw }583};584 585static CLK_FIXED_FACTOR_FW_NAME(osc12m_clk, "osc_12m", "osc_24m", 2, 1, 0);586 587static const char * const out_parents[] = { "osc_24m", "osc_12m" };588 589static struct ccu_div out1_clk = {590	.enable		= BIT(5),591	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),592	.mux		= TH_CCU_ARG(4, 1),593	.common		= {594		.clkid          = CLK_OUT1,595		.cfg0		= 0x1b4,596		.hw.init	= CLK_HW_INIT_PARENTS("out1",597						      out_parents,598						      &ccu_div_ops,599						      0),600	},601};602 603static struct ccu_div out2_clk = {604	.enable		= BIT(5),605	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),606	.mux		= TH_CCU_ARG(4, 1),607	.common		= {608		.clkid          = CLK_OUT2,609		.cfg0		= 0x1b8,610		.hw.init	= CLK_HW_INIT_PARENTS("out2",611						      out_parents,612						      &ccu_div_ops,613						      0),614	},615};616 617static struct ccu_div out3_clk = {618	.enable		= BIT(5),619	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),620	.mux		= TH_CCU_ARG(4, 1),621	.common		= {622		.clkid          = CLK_OUT3,623		.cfg0		= 0x1bc,624		.hw.init	= CLK_HW_INIT_PARENTS("out3",625						      out_parents,626						      &ccu_div_ops,627						      0),628	},629};630 631static struct ccu_div out4_clk = {632	.enable		= BIT(5),633	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),634	.mux		= TH_CCU_ARG(4, 1),635	.common		= {636		.clkid          = CLK_OUT4,637		.cfg0		= 0x1c0,638		.hw.init	= CLK_HW_INIT_PARENTS("out4",639						      out_parents,640						      &ccu_div_ops,641						      0),642	},643};644 645static const struct clk_parent_data apb_parents[] = {646	{ .hw = &gmac_pll_clk.common.hw },647	{ .index = 0 },648};649 650static struct ccu_div apb_pclk = {651	.enable		= BIT(5),652	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),653	.mux		= TH_CCU_ARG(7, 1),654	.common		= {655		.clkid          = CLK_APB_PCLK,656		.cfg0		= 0x1c4,657		.hw.init	= CLK_HW_INIT_PARENTS_DATA("apb-pclk",658						      apb_parents,659						      &ccu_div_ops,660						      0),661	},662};663 664static const struct clk_hw *npu_parents[] = {665	&gmac_pll_clk.common.hw,666	&video_pll_clk.common.hw667};668 669static struct ccu_div npu_clk = {670	.enable		= BIT(4),671	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),672	.mux		= TH_CCU_ARG(6, 1),673	.common		= {674		.clkid          = CLK_NPU,675		.cfg0		= 0x1c8,676		.hw.init	= CLK_HW_INIT_PARENTS_HW("npu",677						      npu_parents,678						      &ccu_div_ops,679						      0),680	},681};682 683static struct ccu_div vi_clk = {684	.div		= TH_CCU_DIV_FLAGS(16, 4, CLK_DIVIDER_ONE_BASED),685	.common		= {686		.clkid          = CLK_VI,687		.cfg0		= 0x1d0,688		.hw.init	= CLK_HW_INIT_PARENTS_HW("vi",689					      video_pll_clk_parent,690					      &ccu_div_ops,691					      0),692	},693};694 695static struct ccu_div vi_ahb_clk = {696	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),697	.common		= {698		.clkid          = CLK_VI_AHB,699		.cfg0		= 0x1d0,700		.hw.init	= CLK_HW_INIT_PARENTS_HW("vi-ahb",701					      video_pll_clk_parent,702					      &ccu_div_ops,703					      0),704	},705};706 707static struct ccu_div vo_axi_clk = {708	.enable		= BIT(5),709	.div		= TH_CCU_DIV_FLAGS(0, 4, CLK_DIVIDER_ONE_BASED),710	.common		= {711		.clkid          = CLK_VO_AXI,712		.cfg0		= 0x1dc,713		.hw.init	= CLK_HW_INIT_PARENTS_HW("vo-axi",714					      video_pll_clk_parent,715					      &ccu_div_ops,716					      0),717	},718};719 720static struct ccu_div vp_apb_clk = {721	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),722	.common		= {723		.clkid          = CLK_VP_APB,724		.cfg0		= 0x1e0,725		.hw.init	= CLK_HW_INIT_PARENTS_HW("vp-apb",726					      gmac_pll_clk_parent,727					      &ccu_div_ops,728					      0),729	},730};731 732static struct ccu_div vp_axi_clk = {733	.enable		= BIT(15),734	.div		= TH_CCU_DIV_FLAGS(8, 4, CLK_DIVIDER_ONE_BASED),735	.common		= {736		.clkid          = CLK_VP_AXI,737		.cfg0		= 0x1e0,738		.hw.init	= CLK_HW_INIT_PARENTS_HW("vp-axi",739					      video_pll_clk_parent,740					      &ccu_div_ops,741					      CLK_IGNORE_UNUSED),742	},743};744 745static struct ccu_div venc_clk = {746	.enable		= BIT(5),747	.div		= TH_CCU_DIV_FLAGS(0, 3, CLK_DIVIDER_ONE_BASED),748	.common		= {749		.clkid          = CLK_VENC,750		.cfg0		= 0x1e4,751		.hw.init	= CLK_HW_INIT_PARENTS_HW("venc",752					      gmac_pll_clk_parent,753					      &ccu_div_ops,754					      0),755	},756};757 758static struct ccu_div dpu0_clk = {759	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),760	.common		= {761		.clkid          = CLK_DPU0,762		.cfg0		= 0x1e8,763		.hw.init	= CLK_HW_INIT_PARENTS_HW("dpu0",764					      dpu0_pll_clk_parent,765					      &ccu_div_ops,766					      0),767	},768};769 770static struct ccu_div dpu1_clk = {771	.div		= TH_CCU_DIV_FLAGS(0, 8, CLK_DIVIDER_ONE_BASED),772	.common		= {773		.clkid          = CLK_DPU1,774		.cfg0		= 0x1ec,775		.hw.init	= CLK_HW_INIT_PARENTS_HW("dpu1",776					      dpu1_pll_clk_parent,777					      &ccu_div_ops,778					      0),779	},780};781 782static CCU_GATE(CLK_BROM, brom_clk, "brom", ahb2_cpusys_hclk_pd, 0x100, BIT(4), 0);783static CCU_GATE(CLK_BMU, bmu_clk, "bmu", axi4_cpusys2_aclk_pd, 0x100, BIT(5), 0);784static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", axi4_cpusys2_aclk_pd,785		0x134, BIT(8), 0);786static CCU_GATE(CLK_X2X_CPUSYS, x2x_cpusys_clk, "x2x-cpusys", axi4_cpusys2_aclk_pd,787		0x134, BIT(7), 0);788static CCU_GATE(CLK_CPU2AON_X2H, cpu2aon_x2h_clk, "cpu2aon-x2h", axi_aclk_pd, 0x138, BIT(8), 0);789static CCU_GATE(CLK_CPU2PERI_X2H, cpu2peri_x2h_clk, "cpu2peri-x2h", axi4_cpusys2_aclk_pd,790		0x140, BIT(9), 0);791static CCU_GATE(CLK_PERISYS_APB1_HCLK, perisys_apb1_hclk, "perisys-apb1-hclk", perisys_ahb_hclk_pd,792		0x150, BIT(9), 0);793static CCU_GATE(CLK_PERISYS_APB2_HCLK, perisys_apb2_hclk, "perisys-apb2-hclk", perisys_ahb_hclk_pd,794		0x150, BIT(10), 0);795static CCU_GATE(CLK_PERISYS_APB3_HCLK, perisys_apb3_hclk, "perisys-apb3-hclk", perisys_ahb_hclk_pd,796		0x150, BIT(11), 0);797static CCU_GATE(CLK_PERISYS_APB4_HCLK, perisys_apb4_hclk, "perisys-apb4-hclk", perisys_ahb_hclk_pd,798		0x150, BIT(12), 0);799static CCU_GATE(CLK_NPU_AXI, npu_axi_clk, "npu-axi", axi_aclk_pd, 0x1c8, BIT(5), 0);800static CCU_GATE(CLK_CPU2VP, cpu2vp_clk, "cpu2vp", axi_aclk_pd, 0x1e0, BIT(13), 0);801static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", video_pll_clk_pd, 0x204, BIT(30), 0);802static CCU_GATE(CLK_GMAC1, gmac1_clk, "gmac1", gmac_pll_clk_pd, 0x204, BIT(26), 0);803static CCU_GATE(CLK_PADCTRL1, padctrl1_clk, "padctrl1", perisys_apb_pclk_pd, 0x204, BIT(24), 0);804static CCU_GATE(CLK_DSMART, dsmart_clk, "dsmart", perisys_apb_pclk_pd, 0x204, BIT(23), 0);805static CCU_GATE(CLK_PADCTRL0, padctrl0_clk, "padctrl0", perisys_apb_pclk_pd, 0x204, BIT(22), 0);806static CCU_GATE(CLK_GMAC_AXI, gmac_axi_clk, "gmac-axi", axi4_cpusys2_aclk_pd, 0x204, BIT(21), 0);807static CCU_GATE(CLK_GPIO3, gpio3_clk, "gpio3-clk", peri2sys_apb_pclk_pd, 0x204, BIT(20), 0);808static CCU_GATE(CLK_GMAC0, gmac0_clk, "gmac0", gmac_pll_clk_pd, 0x204, BIT(19), 0);809static CCU_GATE(CLK_PWM, pwm_clk, "pwm", perisys_apb_pclk_pd, 0x204, BIT(18), 0);810static CCU_GATE(CLK_QSPI0, qspi0_clk, "qspi0", video_pll_clk_pd, 0x204, BIT(17), 0);811static CCU_GATE(CLK_QSPI1, qspi1_clk, "qspi1", video_pll_clk_pd, 0x204, BIT(16), 0);812static CCU_GATE(CLK_SPI, spi_clk, "spi", video_pll_clk_pd, 0x204, BIT(15), 0);813static CCU_GATE(CLK_UART0_PCLK, uart0_pclk, "uart0-pclk", perisys_apb_pclk_pd, 0x204, BIT(14), 0);814static CCU_GATE(CLK_UART1_PCLK, uart1_pclk, "uart1-pclk", perisys_apb_pclk_pd, 0x204, BIT(13), 0);815static CCU_GATE(CLK_UART2_PCLK, uart2_pclk, "uart2-pclk", perisys_apb_pclk_pd, 0x204, BIT(12), 0);816static CCU_GATE(CLK_UART3_PCLK, uart3_pclk, "uart3-pclk", perisys_apb_pclk_pd, 0x204, BIT(11), 0);817static CCU_GATE(CLK_UART4_PCLK, uart4_pclk, "uart4-pclk", perisys_apb_pclk_pd, 0x204, BIT(10), 0);818static CCU_GATE(CLK_UART5_PCLK, uart5_pclk, "uart5-pclk", perisys_apb_pclk_pd, 0x204, BIT(9), 0);819static CCU_GATE(CLK_GPIO0, gpio0_clk, "gpio0-clk", perisys_apb_pclk_pd, 0x204, BIT(8), 0);820static CCU_GATE(CLK_GPIO1, gpio1_clk, "gpio1-clk", perisys_apb_pclk_pd, 0x204, BIT(7), 0);821static CCU_GATE(CLK_GPIO2, gpio2_clk, "gpio2-clk", peri2sys_apb_pclk_pd, 0x204, BIT(6), 0);822static CCU_GATE(CLK_I2C0, i2c0_clk, "i2c0", perisys_apb_pclk_pd, 0x204, BIT(5), 0);823static CCU_GATE(CLK_I2C1, i2c1_clk, "i2c1", perisys_apb_pclk_pd, 0x204, BIT(4), 0);824static CCU_GATE(CLK_I2C2, i2c2_clk, "i2c2", perisys_apb_pclk_pd, 0x204, BIT(3), 0);825static CCU_GATE(CLK_I2C3, i2c3_clk, "i2c3", perisys_apb_pclk_pd, 0x204, BIT(2), 0);826static CCU_GATE(CLK_I2C4, i2c4_clk, "i2c4", perisys_apb_pclk_pd, 0x204, BIT(1), 0);827static CCU_GATE(CLK_I2C5, i2c5_clk, "i2c5", perisys_apb_pclk_pd, 0x204, BIT(0), 0);828static CCU_GATE(CLK_SPINLOCK, spinlock_clk, "spinlock", ahb2_cpusys_hclk_pd, 0x208, BIT(10), 0);829static CCU_GATE(CLK_DMA, dma_clk, "dma", axi4_cpusys2_aclk_pd, 0x208, BIT(8), 0);830static CCU_GATE(CLK_MBOX0, mbox0_clk, "mbox0", apb3_cpusys_pclk_pd, 0x208, BIT(7), 0);831static CCU_GATE(CLK_MBOX1, mbox1_clk, "mbox1", apb3_cpusys_pclk_pd, 0x208, BIT(6), 0);832static CCU_GATE(CLK_MBOX2, mbox2_clk, "mbox2", apb3_cpusys_pclk_pd, 0x208, BIT(5), 0);833static CCU_GATE(CLK_MBOX3, mbox3_clk, "mbox3", apb3_cpusys_pclk_pd, 0x208, BIT(4), 0);834static CCU_GATE(CLK_WDT0, wdt0_clk, "wdt0", apb3_cpusys_pclk_pd, 0x208, BIT(3), 0);835static CCU_GATE(CLK_WDT1, wdt1_clk, "wdt1", apb3_cpusys_pclk_pd, 0x208, BIT(2), 0);836static CCU_GATE(CLK_TIMER0, timer0_clk, "timer0", apb3_cpusys_pclk_pd, 0x208, BIT(1), 0);837static CCU_GATE(CLK_TIMER1, timer1_clk, "timer1", apb3_cpusys_pclk_pd, 0x208, BIT(0), 0);838static CCU_GATE(CLK_SRAM0, sram0_clk, "sram0", axi_aclk_pd, 0x20c, BIT(4), 0);839static CCU_GATE(CLK_SRAM1, sram1_clk, "sram1", axi_aclk_pd, 0x20c, BIT(3), 0);840static CCU_GATE(CLK_SRAM2, sram2_clk, "sram2", axi_aclk_pd, 0x20c, BIT(2), 0);841static CCU_GATE(CLK_SRAM3, sram3_clk, "sram3", axi_aclk_pd, 0x20c, BIT(1), 0);842 843static CLK_FIXED_FACTOR_HW(gmac_pll_clk_100m, "gmac-pll-clk-100m",844			   &gmac_pll_clk.common.hw, 10, 1, 0);845 846static const struct clk_parent_data uart_sclk_parents[] = {847	{ .hw = &gmac_pll_clk_100m.hw },848	{ .index = 0 },849};850 851static struct ccu_mux uart_sclk = {852	.mux	= TH_CCU_ARG(0, 1),853	.common	= {854		.clkid          = CLK_UART_SCLK,855		.cfg0		= 0x210,856		.hw.init	= CLK_HW_INIT_PARENTS_DATA("uart-sclk",857					      uart_sclk_parents,858					      &clk_mux_ops,859					      0),860	}861};862 863static struct ccu_common *th1520_pll_clks[] = {864	&cpu_pll0_clk.common,865	&cpu_pll1_clk.common,866	&gmac_pll_clk.common,867	&video_pll_clk.common,868	&dpu0_pll_clk.common,869	&dpu1_pll_clk.common,870	&tee_pll_clk.common,871};872 873static struct ccu_common *th1520_div_clks[] = {874	&ahb2_cpusys_hclk.common,875	&apb3_cpusys_pclk.common,876	&axi4_cpusys2_aclk.common,877	&perisys_ahb_hclk.common,878	&perisys_apb_pclk.common,879	&axi_aclk.common,880	&peri2sys_apb_pclk.common,881	&out1_clk.common,882	&out2_clk.common,883	&out3_clk.common,884	&out4_clk.common,885	&apb_pclk.common,886	&npu_clk.common,887	&vi_clk.common,888	&vi_ahb_clk.common,889	&vo_axi_clk.common,890	&vp_apb_clk.common,891	&vp_axi_clk.common,892	&cpu2vp_clk.common,893	&venc_clk.common,894	&dpu0_clk.common,895	&dpu1_clk.common,896};897 898static struct ccu_common *th1520_mux_clks[] = {899	&c910_i0_clk.common,900	&c910_clk.common,901	&uart_sclk.common,902};903 904static struct ccu_common *th1520_gate_clks[] = {905	&emmc_sdio_clk.common,906	&aon2cpu_a2x_clk.common,907	&x2x_cpusys_clk.common,908	&brom_clk.common,909	&bmu_clk.common,910	&cpu2aon_x2h_clk.common,911	&cpu2peri_x2h_clk.common,912	&perisys_apb1_hclk.common,913	&perisys_apb2_hclk.common,914	&perisys_apb3_hclk.common,915	&perisys_apb4_hclk.common,916	&npu_axi_clk.common,917	&gmac1_clk.common,918	&padctrl1_clk.common,919	&dsmart_clk.common,920	&padctrl0_clk.common,921	&gmac_axi_clk.common,922	&gpio3_clk.common,923	&gmac0_clk.common,924	&pwm_clk.common,925	&qspi0_clk.common,926	&qspi1_clk.common,927	&spi_clk.common,928	&uart0_pclk.common,929	&uart1_pclk.common,930	&uart2_pclk.common,931	&uart3_pclk.common,932	&uart4_pclk.common,933	&uart5_pclk.common,934	&gpio0_clk.common,935	&gpio1_clk.common,936	&gpio2_clk.common,937	&i2c0_clk.common,938	&i2c1_clk.common,939	&i2c2_clk.common,940	&i2c3_clk.common,941	&i2c4_clk.common,942	&i2c5_clk.common,943	&spinlock_clk.common,944	&dma_clk.common,945	&mbox0_clk.common,946	&mbox1_clk.common,947	&mbox2_clk.common,948	&mbox3_clk.common,949	&wdt0_clk.common,950	&wdt1_clk.common,951	&timer0_clk.common,952	&timer1_clk.common,953	&sram0_clk.common,954	&sram1_clk.common,955	&sram2_clk.common,956	&sram3_clk.common,957};958 959#define NR_CLKS	(CLK_UART_SCLK + 1)960 961static const struct regmap_config th1520_clk_regmap_config = {962	.reg_bits = 32,963	.val_bits = 32,964	.reg_stride = 4,965	.fast_io = true,966};967 968static int th1520_clk_probe(struct platform_device *pdev)969{970	struct device *dev = &pdev->dev;971	struct clk_hw_onecell_data *priv;972 973	struct regmap *map;974	void __iomem *base;975	struct clk_hw *hw;976	int ret, i;977 978	priv = devm_kzalloc(dev, struct_size(priv, hws, NR_CLKS), GFP_KERNEL);979	if (!priv)980		return -ENOMEM;981 982	priv->num = NR_CLKS;983 984	base = devm_platform_ioremap_resource(pdev, 0);985	if (IS_ERR(base))986		return PTR_ERR(base);987 988	map = devm_regmap_init_mmio(dev, base, &th1520_clk_regmap_config);989	if (IS_ERR(map))990		return PTR_ERR(map);991 992	for (i = 0; i < ARRAY_SIZE(th1520_pll_clks); i++) {993		struct ccu_pll *cp = hw_to_ccu_pll(&th1520_pll_clks[i]->hw);994 995		th1520_pll_clks[i]->map = map;996 997		ret = devm_clk_hw_register(dev, &th1520_pll_clks[i]->hw);998		if (ret)999			return ret;1000 1001		priv->hws[cp->common.clkid] = &cp->common.hw;1002	}1003 1004	for (i = 0; i < ARRAY_SIZE(th1520_div_clks); i++) {1005		struct ccu_div *cd = hw_to_ccu_div(&th1520_div_clks[i]->hw);1006 1007		th1520_div_clks[i]->map = map;1008 1009		ret = devm_clk_hw_register(dev, &th1520_div_clks[i]->hw);1010		if (ret)1011			return ret;1012 1013		priv->hws[cd->common.clkid] = &cd->common.hw;1014	}1015 1016	for (i = 0; i < ARRAY_SIZE(th1520_mux_clks); i++) {1017		struct ccu_mux *cm = hw_to_ccu_mux(&th1520_mux_clks[i]->hw);1018		const struct clk_init_data *init = cm->common.hw.init;1019 1020		th1520_mux_clks[i]->map = map;1021		hw = devm_clk_hw_register_mux_parent_data_table(dev,1022								init->name,1023								init->parent_data,1024								init->num_parents,1025								0,1026								base + cm->common.cfg0,1027								cm->mux.shift,1028								cm->mux.width,1029								0, NULL, NULL);1030		if (IS_ERR(hw))1031			return PTR_ERR(hw);1032 1033		priv->hws[cm->common.clkid] = hw;1034	}1035 1036	for (i = 0; i < ARRAY_SIZE(th1520_gate_clks); i++) {1037		struct ccu_gate *cg = hw_to_ccu_gate(&th1520_gate_clks[i]->hw);1038 1039		th1520_gate_clks[i]->map = map;1040 1041		hw = devm_clk_hw_register_gate_parent_data(dev,1042							   cg->common.hw.init->name,1043							   cg->common.hw.init->parent_data,1044							   0, base + cg->common.cfg0,1045							   ffs(cg->enable) - 1, 0, NULL);1046		if (IS_ERR(hw))1047			return PTR_ERR(hw);1048 1049		priv->hws[cg->common.clkid] = hw;1050	}1051 1052	ret = devm_clk_hw_register(dev, &osc12m_clk.hw);1053	if (ret)1054		return ret;1055	priv->hws[CLK_OSC12M] = &osc12m_clk.hw;1056 1057	ret = devm_clk_hw_register(dev, &gmac_pll_clk_100m.hw);1058	if (ret)1059		return ret;1060	priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;1061 1062	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);1063	if (ret)1064		return ret;1065 1066	return 0;1067}1068 1069static const struct of_device_id th1520_clk_match[] = {1070	{1071		.compatible = "thead,th1520-clk-ap",1072	},1073	{ /* sentinel */ },1074};1075MODULE_DEVICE_TABLE(of, th1520_clk_match);1076 1077static struct platform_driver th1520_clk_driver = {1078	.probe		= th1520_clk_probe,1079	.driver		= {1080		.name	= "th1520-clk",1081		.of_match_table = th1520_clk_match,1082	},1083};1084module_platform_driver(th1520_clk_driver);1085 1086MODULE_DESCRIPTION("T-HEAD TH1520 AP Clock driver");1087MODULE_AUTHOR("Yangtao Li <frank.li@vivo.com>");1088MODULE_AUTHOR("Jisheng Zhang <jszhang@kernel.org>");1089MODULE_LICENSE("GPL");1090