brintos

brintos / linux-shallow public Read only

0
0
Text · 10.0 KiB · df479a6 Raw
409 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2018-2020, 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/pm_runtime.h>10#include <linux/regmap.h>11 12#include <dt-bindings/clock/qcom,videocc-sm8250.h>13 14#include "clk-alpha-pll.h"15#include "clk-branch.h"16#include "clk-rcg.h"17#include "clk-regmap.h"18#include "clk-regmap-divider.h"19#include "common.h"20#include "reset.h"21#include "gdsc.h"22 23enum {24	P_BI_TCXO,25	P_VIDEO_PLL0_OUT_MAIN,26	P_VIDEO_PLL1_OUT_MAIN,27};28 29static const struct pll_vco lucid_vco[] = {30	{ 249600000, 2000000000, 0 },31};32 33static const struct alpha_pll_config video_pll0_config = {34	.l = 0x25,35	.alpha = 0x8000,36	.config_ctl_val = 0x20485699,37	.config_ctl_hi_val = 0x00002261,38	.config_ctl_hi1_val = 0x329A699C,39	.user_ctl_val = 0x00000000,40	.user_ctl_hi_val = 0x00000805,41	.user_ctl_hi1_val = 0x00000000,42};43 44static struct clk_alpha_pll video_pll0 = {45	.offset = 0x42c,46	.vco_table = lucid_vco,47	.num_vco = ARRAY_SIZE(lucid_vco),48	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],49	.clkr = {50		.hw.init = &(struct clk_init_data){51			.name = "video_pll0",52			.parent_data = &(const struct clk_parent_data){53				.fw_name = "bi_tcxo",54			},55			.num_parents = 1,56			.ops = &clk_alpha_pll_lucid_ops,57		},58	},59};60 61static const struct alpha_pll_config video_pll1_config = {62	.l = 0x2B,63	.alpha = 0xC000,64	.config_ctl_val = 0x20485699,65	.config_ctl_hi_val = 0x00002261,66	.config_ctl_hi1_val = 0x329A699C,67	.user_ctl_val = 0x00000000,68	.user_ctl_hi_val = 0x00000805,69	.user_ctl_hi1_val = 0x00000000,70};71 72static struct clk_alpha_pll video_pll1 = {73	.offset = 0x7d0,74	.vco_table = lucid_vco,75	.num_vco = ARRAY_SIZE(lucid_vco),76	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],77	.clkr = {78		.hw.init = &(struct clk_init_data){79			.name = "video_pll1",80			.parent_data = &(const struct clk_parent_data){81				.fw_name = "bi_tcxo",82			},83			.num_parents = 1,84			.ops = &clk_alpha_pll_lucid_ops,85		},86	},87};88 89static const struct parent_map video_cc_parent_map_1[] = {90	{ P_BI_TCXO, 0 },91	{ P_VIDEO_PLL0_OUT_MAIN, 1 },92};93 94static const struct clk_parent_data video_cc_parent_data_1[] = {95	{ .fw_name = "bi_tcxo" },96	{ .hw = &video_pll0.clkr.hw },97};98 99static const struct parent_map video_cc_parent_map_2[] = {100	{ P_BI_TCXO, 0 },101	{ P_VIDEO_PLL1_OUT_MAIN, 1 },102};103 104static const struct clk_parent_data video_cc_parent_data_2[] = {105	{ .fw_name = "bi_tcxo" },106	{ .hw = &video_pll1.clkr.hw },107};108 109static const struct freq_tbl ftbl_video_cc_mvs0_clk_src[] = {110	F(19200000, P_BI_TCXO, 1, 0, 0),111	F(720000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),112	F(1014000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),113	F(1098000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),114	F(1332000000, P_VIDEO_PLL0_OUT_MAIN, 1, 0, 0),115	{ }116};117 118static struct clk_rcg2 video_cc_mvs0_clk_src = {119	.cmd_rcgr = 0xb94,120	.mnd_width = 0,121	.hid_width = 5,122	.parent_map = video_cc_parent_map_1,123	.freq_tbl = ftbl_video_cc_mvs0_clk_src,124	.clkr.hw.init = &(struct clk_init_data){125		.name = "video_cc_mvs0_clk_src",126		.parent_data = video_cc_parent_data_1,127		.num_parents = ARRAY_SIZE(video_cc_parent_data_1),128		.flags = CLK_SET_RATE_PARENT,129		.ops = &clk_rcg2_shared_ops,130	},131};132 133static const struct freq_tbl ftbl_video_cc_mvs1_clk_src[] = {134	F(19200000, P_BI_TCXO, 1, 0, 0),135	F(840000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),136	F(1098000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),137	F(1332000000, P_VIDEO_PLL1_OUT_MAIN, 1, 0, 0),138	{ }139};140 141static struct clk_rcg2 video_cc_mvs1_clk_src = {142	.cmd_rcgr = 0xbb4,143	.mnd_width = 0,144	.hid_width = 5,145	.parent_map = video_cc_parent_map_2,146	.freq_tbl = ftbl_video_cc_mvs1_clk_src,147	.clkr.hw.init = &(struct clk_init_data){148		.name = "video_cc_mvs1_clk_src",149		.parent_data = video_cc_parent_data_2,150		.num_parents = ARRAY_SIZE(video_cc_parent_data_2),151		.flags = CLK_SET_RATE_PARENT,152		.ops = &clk_rcg2_shared_ops,153	},154};155 156static struct clk_regmap_div video_cc_mvs0c_div2_div_clk_src = {157	.reg = 0xc54,158	.shift = 0,159	.width = 2,160	.clkr.hw.init = &(struct clk_init_data) {161		.name = "video_cc_mvs0c_div2_div_clk_src",162		.parent_hws = (const struct clk_hw*[]){163			&video_cc_mvs0_clk_src.clkr.hw,164		},165		.num_parents = 1,166		.flags = CLK_SET_RATE_PARENT,167		.ops = &clk_regmap_div_ro_ops,168	},169};170 171static struct clk_regmap_div video_cc_mvs0_div_clk_src = {172	.reg = 0xd54,173	.shift = 0,174	.width = 2,175	.clkr.hw.init = &(struct clk_init_data) {176		.name = "video_cc_mvs0_div_clk_src",177		.parent_hws = (const struct clk_hw*[]){178			&video_cc_mvs0_clk_src.clkr.hw,179		},180		.num_parents = 1,181		.flags = CLK_SET_RATE_PARENT,182		.ops = &clk_regmap_div_ro_ops,183	},184};185 186static struct clk_regmap_div video_cc_mvs1c_div2_div_clk_src = {187	.reg = 0xcf4,188	.shift = 0,189	.width = 2,190	.clkr.hw.init = &(struct clk_init_data) {191		.name = "video_cc_mvs1c_div2_div_clk_src",192		.parent_hws = (const struct clk_hw*[]){193			&video_cc_mvs1_clk_src.clkr.hw,194		},195		.num_parents = 1,196		.flags = CLK_SET_RATE_PARENT,197		.ops = &clk_regmap_div_ro_ops,198	},199};200 201static struct clk_branch video_cc_mvs0c_clk = {202	.halt_reg = 0xc34,203	.halt_check = BRANCH_HALT,204	.clkr = {205		.enable_reg = 0xc34,206		.enable_mask = BIT(0),207		.hw.init = &(struct clk_init_data){208			.name = "video_cc_mvs0c_clk",209			.parent_hws = (const struct clk_hw*[]){210				&video_cc_mvs0c_div2_div_clk_src.clkr.hw,211			},212			.num_parents = 1,213			.flags = CLK_SET_RATE_PARENT,214			.ops = &clk_branch2_ops,215		},216	},217};218 219static struct clk_branch video_cc_mvs0_clk = {220	.halt_reg = 0xd34,221	.halt_check = BRANCH_HALT_VOTED,222	.clkr = {223		.enable_reg = 0xd34,224		.enable_mask = BIT(0),225		.hw.init = &(struct clk_init_data){226			.name = "video_cc_mvs0_clk",227			.parent_hws = (const struct clk_hw*[]){228				&video_cc_mvs0_div_clk_src.clkr.hw,229			},230			.num_parents = 1,231			.flags = CLK_SET_RATE_PARENT,232			.ops = &clk_branch2_ops,233		},234	},235};236 237static struct clk_branch video_cc_mvs1_div2_clk = {238	.halt_reg = 0xdf4,239	.halt_check = BRANCH_HALT_VOTED,240	.clkr = {241		.enable_reg = 0xdf4,242		.enable_mask = BIT(0),243		.hw.init = &(struct clk_init_data){244			.name = "video_cc_mvs1_div2_clk",245			.parent_hws = (const struct clk_hw*[]){246				&video_cc_mvs1c_div2_div_clk_src.clkr.hw,247			},248			.num_parents = 1,249			.flags = CLK_SET_RATE_PARENT,250			.ops = &clk_branch2_ops,251		},252	},253};254 255static struct clk_branch video_cc_mvs1c_clk = {256	.halt_reg = 0xcd4,257	.halt_check = BRANCH_HALT_VOTED,258	.clkr = {259		.enable_reg = 0xcd4,260		.enable_mask = BIT(0),261		.hw.init = &(struct clk_init_data){262			.name = "video_cc_mvs1c_clk",263			.parent_hws = (const struct clk_hw*[]){264				&video_cc_mvs1c_div2_div_clk_src.clkr.hw,265			},266			.num_parents = 1,267			.flags = CLK_SET_RATE_PARENT,268			.ops = &clk_branch2_ops,269		},270	},271};272 273static struct gdsc mvs0c_gdsc = {274	.gdscr = 0xbf8,275	.pd = {276		.name = "mvs0c_gdsc",277	},278	.flags = 0,279	.pwrsts = PWRSTS_OFF_ON,280};281 282static struct gdsc mvs1c_gdsc = {283	.gdscr = 0xc98,284	.pd = {285		.name = "mvs1c_gdsc",286	},287	.flags = 0,288	.pwrsts = PWRSTS_OFF_ON,289};290 291static struct gdsc mvs0_gdsc = {292	.gdscr = 0xd18,293	.pd = {294		.name = "mvs0_gdsc",295	},296	.flags = HW_CTRL_TRIGGER,297	.pwrsts = PWRSTS_OFF_ON,298};299 300static struct gdsc mvs1_gdsc = {301	.gdscr = 0xd98,302	.pd = {303		.name = "mvs1_gdsc",304	},305	.flags = HW_CTRL_TRIGGER,306	.pwrsts = PWRSTS_OFF_ON,307};308 309static struct clk_regmap *video_cc_sm8250_clocks[] = {310	[VIDEO_CC_MVS0_CLK] = &video_cc_mvs0_clk.clkr,311	[VIDEO_CC_MVS0_CLK_SRC] = &video_cc_mvs0_clk_src.clkr,312	[VIDEO_CC_MVS0_DIV_CLK_SRC] = &video_cc_mvs0_div_clk_src.clkr,313	[VIDEO_CC_MVS0C_CLK] = &video_cc_mvs0c_clk.clkr,314	[VIDEO_CC_MVS0C_DIV2_DIV_CLK_SRC] = &video_cc_mvs0c_div2_div_clk_src.clkr,315	[VIDEO_CC_MVS1_CLK_SRC] = &video_cc_mvs1_clk_src.clkr,316	[VIDEO_CC_MVS1_DIV2_CLK] = &video_cc_mvs1_div2_clk.clkr,317	[VIDEO_CC_MVS1C_CLK] = &video_cc_mvs1c_clk.clkr,318	[VIDEO_CC_MVS1C_DIV2_DIV_CLK_SRC] = &video_cc_mvs1c_div2_div_clk_src.clkr,319	[VIDEO_CC_PLL0] = &video_pll0.clkr,320	[VIDEO_CC_PLL1] = &video_pll1.clkr,321};322 323static const struct qcom_reset_map video_cc_sm8250_resets[] = {324	[VIDEO_CC_CVP_INTERFACE_BCR] = { 0xe54 },325	[VIDEO_CC_CVP_MVS0_BCR] = { 0xd14 },326	[VIDEO_CC_MVS0C_CLK_ARES] = { 0xc34, .bit = 2, .udelay = 150 },327	[VIDEO_CC_CVP_MVS0C_BCR] = { 0xbf4 },328	[VIDEO_CC_CVP_MVS1_BCR] = { 0xd94 },329	[VIDEO_CC_MVS1C_CLK_ARES] = { 0xcd4, .bit = 2, .udelay = 150 },330	[VIDEO_CC_CVP_MVS1C_BCR] = { 0xc94 },331};332 333static struct gdsc *video_cc_sm8250_gdscs[] = {334	[MVS0C_GDSC] = &mvs0c_gdsc,335	[MVS1C_GDSC] = &mvs1c_gdsc,336	[MVS0_GDSC] = &mvs0_gdsc,337	[MVS1_GDSC] = &mvs1_gdsc,338};339 340static const struct regmap_config video_cc_sm8250_regmap_config = {341	.reg_bits = 32,342	.reg_stride = 4,343	.val_bits = 32,344	.max_register = 0xf4c,345	.fast_io = true,346};347 348static const struct qcom_cc_desc video_cc_sm8250_desc = {349	.config = &video_cc_sm8250_regmap_config,350	.clks = video_cc_sm8250_clocks,351	.num_clks = ARRAY_SIZE(video_cc_sm8250_clocks),352	.resets = video_cc_sm8250_resets,353	.num_resets = ARRAY_SIZE(video_cc_sm8250_resets),354	.gdscs = video_cc_sm8250_gdscs,355	.num_gdscs = ARRAY_SIZE(video_cc_sm8250_gdscs),356};357 358static const struct of_device_id video_cc_sm8250_match_table[] = {359	{ .compatible = "qcom,sm8250-videocc" },360	{ }361};362MODULE_DEVICE_TABLE(of, video_cc_sm8250_match_table);363 364static int video_cc_sm8250_probe(struct platform_device *pdev)365{366	struct regmap *regmap;367	int ret;368 369	ret = devm_pm_runtime_enable(&pdev->dev);370	if (ret)371		return ret;372 373	ret = pm_runtime_resume_and_get(&pdev->dev);374	if (ret)375		return ret;376 377	regmap = qcom_cc_map(pdev, &video_cc_sm8250_desc);378	if (IS_ERR(regmap)) {379		pm_runtime_put(&pdev->dev);380		return PTR_ERR(regmap);381	}382 383	clk_lucid_pll_configure(&video_pll0, regmap, &video_pll0_config);384	clk_lucid_pll_configure(&video_pll1, regmap, &video_pll1_config);385 386	/* Keep some clocks always-on */387	qcom_branch_set_clk_en(regmap, 0xe58); /* VIDEO_CC_AHB_CLK */388	qcom_branch_set_clk_en(regmap, 0xeec); /* VIDEO_CC_XO_CLK */389 390	ret = qcom_cc_really_probe(&pdev->dev, &video_cc_sm8250_desc, regmap);391 392	pm_runtime_put(&pdev->dev);393 394	return ret;395}396 397static struct platform_driver video_cc_sm8250_driver = {398	.probe	= video_cc_sm8250_probe,399	.driver	= {400		.name = "sm8250-videocc",401		.of_match_table = video_cc_sm8250_match_table,402	},403};404 405module_platform_driver(video_cc_sm8250_driver);406 407MODULE_LICENSE("GPL v2");408MODULE_DESCRIPTION("QTI VIDEOCC SM8250 Driver");409