Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2018, The Linux Foundation. All rights reserved.
  4 */
  5
  6#include <linux/clk-provider.h>
  7#include <linux/module.h>
  8#include <linux/platform_device.h>
  9#include <linux/regmap.h>
 10
 11#include <dt-bindings/clock/qcom,videocc-sdm845.h>
 12
 13#include "common.h"
 14#include "clk-alpha-pll.h"
 15#include "clk-branch.h"
 16#include "clk-rcg.h"
 17#include "clk-regmap.h"
 18#include "clk-pll.h"
 19#include "gdsc.h"
 20
 21enum {
 22	P_BI_TCXO,
 23	P_VIDEO_PLL0_OUT_MAIN,
 24	/* P_VIDEO_PLL0_OUT_EVEN, */
 25	/* P_VIDEO_PLL0_OUT_ODD, */
 26};
 27
 28static const struct alpha_pll_config video_pll0_config = {
 29	.l = 0x10,
 30	.alpha = 0xaaab,
 31};
 32
 33static struct clk_alpha_pll video_pll0 = {
 34	.offset = 0x42c,
 35	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],
 36	.clkr = {
 37		.hw.init = &(struct clk_init_data){
 38			.name = "video_pll0",
 39			.parent_data = &(const struct clk_parent_data){
 40				.fw_name = "bi_tcxo", .name = "bi_tcxo",
 41			},
 42			.num_parents = 1,
 43			.ops = &clk_alpha_pll_fabia_ops,
 44		},
 45	},
 46};
 47
 48static const struct parent_map video_cc_parent_map_0[] = {
 49	{ P_BI_TCXO, 0 },
 50	{ P_VIDEO_PLL0_OUT_MAIN, 1 },
 51	/* { P_VIDEO_PLL0_OUT_EVEN, 2 }, */
 52	/* { P_VIDEO_PLL0_OUT_ODD, 3 }, */
 53};
 54
 55static const struct clk_parent_data video_cc_parent_data_0[] = {
 56	{ .fw_name = "bi_tcxo", .name = "bi_tcxo" },
 57	{ .hw = &video_pll0.clkr.hw },
 58	/* { .name = "video_pll0_out_even" }, */
 59	/* { .name = "video_pll0_out_odd" }, */
 60};
 61
 62static const struct freq_tbl ftbl_video_cc_venus_clk_src[] = {
 63	F(100000000, P_VIDEO_PLL0_OUT_MAIN, 4, 0, 0),
 64	F(200000000, P_VIDEO_PLL0_OUT_MAIN, 2, 0, 0),
 65	F(330000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
 66	F(404000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
 67	F(444000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
 68	F(533000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),
 69	{ }
 70};
 71
 72static struct clk_rcg2 video_cc_venus_clk_src = {
 73	.cmd_rcgr = 0x7f0,
 74	.mnd_width = 0,
 75	.hid_width = 5,
 76	.parent_map = video_cc_parent_map_0,
 77	.freq_tbl = ftbl_video_cc_venus_clk_src,
 78	.clkr.hw.init = &(struct clk_init_data){
 79		.name = "video_cc_venus_clk_src",
 80		.parent_data = video_cc_parent_data_0,
 81		.num_parents = ARRAY_SIZE(video_cc_parent_data_0),
 82		.flags = CLK_SET_RATE_PARENT,
 83		.ops = &clk_rcg2_shared_ops,
 84	},
 85};
 86
 87static struct clk_branch video_cc_apb_clk = {
 88	.halt_reg = 0x990,
 89	.halt_check = BRANCH_HALT,
 90	.clkr = {
 91		.enable_reg = 0x990,
 92		.enable_mask = BIT(0),
 93		.hw.init = &(struct clk_init_data){
 94			.name = "video_cc_apb_clk",
 95			.ops = &clk_branch2_ops,
 96		},
 97	},
 98};
 99
100static struct clk_branch video_cc_at_clk = {
101	.halt_reg = 0x9f0,
102	.halt_check = BRANCH_HALT,
103	.clkr = {
104		.enable_reg = 0x9f0,
105		.enable_mask = BIT(0),
106		.hw.init = &(struct clk_init_data){
107			.name = "video_cc_at_clk",
108			.ops = &clk_branch2_ops,
109		},
110	},
111};
112
113static struct clk_branch video_cc_qdss_trig_clk = {
114	.halt_reg = 0x970,
115	.halt_check = BRANCH_HALT,
116	.clkr = {
117		.enable_reg = 0x970,
118		.enable_mask = BIT(0),
119		.hw.init = &(struct clk_init_data){
120			.name = "video_cc_qdss_trig_clk",
121			.ops = &clk_branch2_ops,
122		},
123	},
124};
125
126static struct clk_branch video_cc_qdss_tsctr_div8_clk = {
127	.halt_reg = 0x9d0,
128	.halt_check = BRANCH_HALT,
129	.clkr = {
130		.enable_reg = 0x9d0,
131		.enable_mask = BIT(0),
132		.hw.init = &(struct clk_init_data){
133			.name = "video_cc_qdss_tsctr_div8_clk",
134			.ops = &clk_branch2_ops,
135		},
136	},
137};
138
139static struct clk_branch video_cc_vcodec0_axi_clk = {
140	.halt_reg = 0x930,
141	.halt_check = BRANCH_HALT,
142	.clkr = {
143		.enable_reg = 0x930,
144		.enable_mask = BIT(0),
145		.hw.init = &(struct clk_init_data){
146			.name = "video_cc_vcodec0_axi_clk",
147			.ops = &clk_branch2_ops,
148		},
149	},
150};
151
152static struct clk_branch video_cc_vcodec0_core_clk = {
153	.halt_reg = 0x890,
154	.halt_check = BRANCH_VOTED,
155	.clkr = {
156		.enable_reg = 0x890,
157		.enable_mask = BIT(0),
158		.hw.init = &(struct clk_init_data){
159			.name = "video_cc_vcodec0_core_clk",
160			.parent_hws = (const struct clk_hw*[]){
161				&video_cc_venus_clk_src.clkr.hw,
162			},
163			.num_parents = 1,
164			.flags = CLK_SET_RATE_PARENT,
165			.ops = &clk_branch2_ops,
166		},
167	},
168};
169
170static struct clk_branch video_cc_vcodec1_axi_clk = {
171	.halt_reg = 0x950,
172	.halt_check = BRANCH_HALT,
173	.clkr = {
174		.enable_reg = 0x950,
175		.enable_mask = BIT(0),
176		.hw.init = &(struct clk_init_data){
177			.name = "video_cc_vcodec1_axi_clk",
178			.ops = &clk_branch2_ops,
179		},
180	},
181};
182
183static struct clk_branch video_cc_vcodec1_core_clk = {
184	.halt_reg = 0x8d0,
185	.halt_check = BRANCH_VOTED,
186	.clkr = {
187		.enable_reg = 0x8d0,
188		.enable_mask = BIT(0),
189		.hw.init = &(struct clk_init_data){
190			.name = "video_cc_vcodec1_core_clk",
191			.parent_hws = (const struct clk_hw*[]){
192				&video_cc_venus_clk_src.clkr.hw,
193			},
194			.num_parents = 1,
195			.flags = CLK_SET_RATE_PARENT,
196			.ops = &clk_branch2_ops,
197		},
198	},
199};
200
201static struct clk_branch video_cc_venus_ahb_clk = {
202	.halt_reg = 0x9b0,
203	.halt_check = BRANCH_HALT,
204	.clkr = {
205		.enable_reg = 0x9b0,
206		.enable_mask = BIT(0),
207		.hw.init = &(struct clk_init_data){
208			.name = "video_cc_venus_ahb_clk",
209			.ops = &clk_branch2_ops,
210		},
211	},
212};
213
214static struct clk_branch video_cc_venus_ctl_axi_clk = {
215	.halt_reg = 0x910,
216	.halt_check = BRANCH_HALT,
217	.clkr = {
218		.enable_reg = 0x910,
219		.enable_mask = BIT(0),
220		.hw.init = &(struct clk_init_data){
221			.name = "video_cc_venus_ctl_axi_clk",
222			.ops = &clk_branch2_ops,
223		},
224	},
225};
226
227static struct clk_branch video_cc_venus_ctl_core_clk = {
228	.halt_reg = 0x850,
229	.halt_check = BRANCH_HALT,
230	.clkr = {
231		.enable_reg = 0x850,
232		.enable_mask = BIT(0),
233		.hw.init = &(struct clk_init_data){
234			.name = "video_cc_venus_ctl_core_clk",
235			.parent_hws = (const struct clk_hw*[]){
236				&video_cc_venus_clk_src.clkr.hw,
237			},
238			.num_parents = 1,
239			.flags = CLK_SET_RATE_PARENT,
240			.ops = &clk_branch2_ops,
241		},
242	},
243};
244
245static struct gdsc venus_gdsc = {
246	.gdscr = 0x814,
247	.pd = {
248		.name = "venus_gdsc",
249	},
250	.cxcs = (unsigned int []){ 0x850, 0x910 },
251	.cxc_count = 2,
252	.pwrsts = PWRSTS_OFF_ON,
253	.flags = POLL_CFG_GDSCR,
254};
255
256static struct gdsc vcodec0_gdsc = {
257	.gdscr = 0x874,
258	.pd = {
259		.name = "vcodec0_gdsc",
260	},
261	.cxcs = (unsigned int []){ 0x890, 0x930 },
262	.cxc_count = 2,
263	.flags = HW_CTRL | POLL_CFG_GDSCR,
264	.pwrsts = PWRSTS_OFF_ON,
265};
266
267static struct gdsc vcodec1_gdsc = {
268	.gdscr = 0x8b4,
269	.pd = {
270		.name = "vcodec1_gdsc",
271	},
272	.cxcs = (unsigned int []){ 0x8d0, 0x950 },
273	.cxc_count = 2,
274	.flags = HW_CTRL | POLL_CFG_GDSCR,
275	.pwrsts = PWRSTS_OFF_ON,
276};
277
278static struct clk_regmap *video_cc_sdm845_clocks[] = {
279	[VIDEO_CC_APB_CLK] = &video_cc_apb_clk.clkr,
280	[VIDEO_CC_AT_CLK] = &video_cc_at_clk.clkr,
281	[VIDEO_CC_QDSS_TRIG_CLK] = &video_cc_qdss_trig_clk.clkr,
282	[VIDEO_CC_QDSS_TSCTR_DIV8_CLK] = &video_cc_qdss_tsctr_div8_clk.clkr,
283	[VIDEO_CC_VCODEC0_AXI_CLK] = &video_cc_vcodec0_axi_clk.clkr,
284	[VIDEO_CC_VCODEC0_CORE_CLK] = &video_cc_vcodec0_core_clk.clkr,
285	[VIDEO_CC_VCODEC1_AXI_CLK] = &video_cc_vcodec1_axi_clk.clkr,
286	[VIDEO_CC_VCODEC1_CORE_CLK] = &video_cc_vcodec1_core_clk.clkr,
287	[VIDEO_CC_VENUS_AHB_CLK] = &video_cc_venus_ahb_clk.clkr,
288	[VIDEO_CC_VENUS_CLK_SRC] = &video_cc_venus_clk_src.clkr,
289	[VIDEO_CC_VENUS_CTL_AXI_CLK] = &video_cc_venus_ctl_axi_clk.clkr,
290	[VIDEO_CC_VENUS_CTL_CORE_CLK] = &video_cc_venus_ctl_core_clk.clkr,
291	[VIDEO_PLL0] = &video_pll0.clkr,
292};
293
294static struct gdsc *video_cc_sdm845_gdscs[] = {
295	[VENUS_GDSC] = &venus_gdsc,
296	[VCODEC0_GDSC] = &vcodec0_gdsc,
297	[VCODEC1_GDSC] = &vcodec1_gdsc,
298};
299
300static const struct regmap_config video_cc_sdm845_regmap_config = {
301	.reg_bits	= 32,
302	.reg_stride	= 4,
303	.val_bits	= 32,
304	.max_register	= 0xb90,
305	.fast_io	= true,
306};
307
308static const struct qcom_cc_desc video_cc_sdm845_desc = {
309	.config = &video_cc_sdm845_regmap_config,
310	.clks = video_cc_sdm845_clocks,
311	.num_clks = ARRAY_SIZE(video_cc_sdm845_clocks),
312	.gdscs = video_cc_sdm845_gdscs,
313	.num_gdscs = ARRAY_SIZE(video_cc_sdm845_gdscs),
314};
315
316static const struct of_device_id video_cc_sdm845_match_table[] = {
317	{ .compatible = "qcom,sdm845-videocc" },
318	{ }
319};
320MODULE_DEVICE_TABLE(of, video_cc_sdm845_match_table);
321
322static int video_cc_sdm845_probe(struct platform_device *pdev)
323{
324	struct regmap *regmap;
325
326	regmap = qcom_cc_map(pdev, &video_cc_sdm845_desc);
327	if (IS_ERR(regmap))
328		return PTR_ERR(regmap);
329
330	clk_fabia_pll_configure(&video_pll0, regmap, &video_pll0_config);
331
332	return qcom_cc_really_probe(pdev, &video_cc_sdm845_desc, regmap);
333}
334
335static struct platform_driver video_cc_sdm845_driver = {
336	.probe		= video_cc_sdm845_probe,
337	.driver		= {
338		.name	= "sdm845-videocc",
339		.of_match_table = video_cc_sdm845_match_table,
340	},
341};
342
343static int __init video_cc_sdm845_init(void)
344{
345	return platform_driver_register(&video_cc_sdm845_driver);
346}
347subsys_initcall(video_cc_sdm845_init);
348
349static void __exit video_cc_sdm845_exit(void)
350{
351	platform_driver_unregister(&video_cc_sdm845_driver);
352}
353module_exit(video_cc_sdm845_exit);
354
355MODULE_LICENSE("GPL v2");