brintos

brintos / linux-shallow public Read only

0
0
Text · 13.9 KiB · 449ffea Raw
546 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2020, The Linux Foundation. All rights reserved.4 * Copyright (c) 2021, Linaro Ltd.5 */6 7#include <linux/err.h>8#include <linux/kernel.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/platform_device.h>12#include <linux/regmap.h>13 14#include <dt-bindings/clock/qcom,dispcc-qcm2290.h>15 16#include "clk-alpha-pll.h"17#include "clk-branch.h"18#include "clk-rcg.h"19#include "clk-regmap.h"20#include "clk-regmap-divider.h"21#include "common.h"22#include "gdsc.h"23#include "reset.h"24 25enum {26	P_BI_TCXO,27	P_BI_TCXO_AO,28	P_DISP_CC_PLL0_OUT_MAIN,29	P_DSI0_PHY_PLL_OUT_BYTECLK,30	P_DSI0_PHY_PLL_OUT_DSICLK,31	P_GPLL0_OUT_DIV,32	P_GPLL0_OUT_MAIN,33	P_SLEEP_CLK,34};35 36static const struct pll_vco spark_vco[] = {37	{ 500000000, 1000000000, 2 },38};39 40/* 768MHz configuration */41static const struct alpha_pll_config disp_cc_pll0_config = {42	.l = 0x28,43	.alpha = 0x0,44	.alpha_en_mask = BIT(24),45	.vco_val = 0x2 << 20,46	.vco_mask = GENMASK(21, 20),47	.main_output_mask = BIT(0),48	.config_ctl_val = 0x4001055B,49};50 51static struct clk_alpha_pll disp_cc_pll0 = {52	.offset = 0x0,53	.vco_table = spark_vco,54	.num_vco = ARRAY_SIZE(spark_vco),55	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_DEFAULT],56	.clkr = {57		.hw.init = &(struct clk_init_data){58			.name = "disp_cc_pll0",59			.parent_data = &(const struct clk_parent_data){60				.fw_name = "bi_tcxo",61			},62			.num_parents = 1,63			.ops = &clk_alpha_pll_ops,64		},65	},66};67 68static const struct parent_map disp_cc_parent_map_0[] = {69	{ P_BI_TCXO, 0 },70	{ P_DSI0_PHY_PLL_OUT_BYTECLK, 1 },71};72 73static const struct clk_parent_data disp_cc_parent_data_0[] = {74	{ .fw_name = "bi_tcxo" },75	{ .fw_name = "dsi0_phy_pll_out_byteclk" },76};77 78static const struct parent_map disp_cc_parent_map_1[] = {79	{ P_BI_TCXO, 0 },80};81 82static const struct clk_parent_data disp_cc_parent_data_1[] = {83	{ .fw_name = "bi_tcxo" },84};85 86static const struct parent_map disp_cc_parent_map_2[] = {87	{ P_BI_TCXO_AO, 0 },88	{ P_GPLL0_OUT_DIV, 4 },89};90 91static const struct clk_parent_data disp_cc_parent_data_2[] = {92	{ .fw_name = "bi_tcxo_ao" },93	{ .fw_name = "gcc_disp_gpll0_div_clk_src" },94};95 96static const struct parent_map disp_cc_parent_map_3[] = {97	{ P_BI_TCXO, 0 },98	{ P_DISP_CC_PLL0_OUT_MAIN, 1 },99	{ P_GPLL0_OUT_MAIN, 4 },100};101 102static const struct clk_parent_data disp_cc_parent_data_3[] = {103	{ .fw_name = "bi_tcxo" },104	{ .hw = &disp_cc_pll0.clkr.hw },105	{ .fw_name = "gcc_disp_gpll0_clk_src" },106};107 108static const struct parent_map disp_cc_parent_map_4[] = {109	{ P_BI_TCXO, 0 },110	{ P_DSI0_PHY_PLL_OUT_DSICLK, 1 },111};112 113static const struct clk_parent_data disp_cc_parent_data_4[] = {114	{ .fw_name = "bi_tcxo" },115	{ .fw_name = "dsi0_phy_pll_out_dsiclk" },116};117 118static const struct parent_map disp_cc_parent_map_5[] = {119	{ P_SLEEP_CLK, 0 },120};121 122static const struct clk_parent_data disp_cc_parent_data_5[] = {123	{ .fw_name = "sleep_clk" },124};125 126static struct clk_rcg2 disp_cc_mdss_byte0_clk_src = {127	.cmd_rcgr = 0x20a4,128	.mnd_width = 0,129	.hid_width = 5,130	.parent_map = disp_cc_parent_map_0,131	.clkr.hw.init = &(struct clk_init_data){132		.name = "disp_cc_mdss_byte0_clk_src",133		.parent_data = disp_cc_parent_data_0,134		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),135		/* For set_rate and set_parent to succeed, parent(s) must be enabled */136		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,137		.ops = &clk_byte2_ops,138	},139};140 141static struct clk_regmap_div disp_cc_mdss_byte0_div_clk_src = {142	.reg = 0x20bc,143	.shift = 0,144	.width = 2,145	.clkr.hw.init = &(struct clk_init_data) {146		.name = "disp_cc_mdss_byte0_div_clk_src",147		.parent_hws = (const struct clk_hw*[]){148			&disp_cc_mdss_byte0_clk_src.clkr.hw,149		},150		.num_parents = 1,151		.ops = &clk_regmap_div_ops,152	},153};154 155static const struct freq_tbl ftbl_disp_cc_mdss_ahb_clk_src[] = {156	F(19200000, P_BI_TCXO_AO, 1, 0, 0),157	F(37500000, P_GPLL0_OUT_DIV, 8, 0, 0),158	F(75000000, P_GPLL0_OUT_DIV, 4, 0, 0),159	{ }160};161 162static struct clk_rcg2 disp_cc_mdss_ahb_clk_src = {163	.cmd_rcgr = 0x2154,164	.mnd_width = 0,165	.hid_width = 5,166	.parent_map = disp_cc_parent_map_2,167	.freq_tbl = ftbl_disp_cc_mdss_ahb_clk_src,168	.clkr.hw.init = &(struct clk_init_data){169		.name = "disp_cc_mdss_ahb_clk_src",170		.parent_data = disp_cc_parent_data_2,171		.num_parents = ARRAY_SIZE(disp_cc_parent_data_2),172		.ops = &clk_rcg2_shared_ops,173	},174};175 176static const struct freq_tbl ftbl_disp_cc_mdss_esc0_clk_src[] = {177	F(19200000, P_BI_TCXO, 1, 0, 0),178	{ }179};180 181static struct clk_rcg2 disp_cc_mdss_esc0_clk_src = {182	.cmd_rcgr = 0x20c0,183	.mnd_width = 0,184	.hid_width = 5,185	.parent_map = disp_cc_parent_map_0,186	.freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,187	.clkr.hw.init = &(struct clk_init_data){188		.name = "disp_cc_mdss_esc0_clk_src",189		.parent_data = disp_cc_parent_data_0,190		.num_parents = ARRAY_SIZE(disp_cc_parent_data_0),191		.ops = &clk_rcg2_ops,192	},193};194 195static const struct freq_tbl ftbl_disp_cc_mdss_mdp_clk_src[] = {196	F(19200000, P_BI_TCXO, 1, 0, 0),197	F(192000000, P_DISP_CC_PLL0_OUT_MAIN, 4, 0, 0),198	F(256000000, P_DISP_CC_PLL0_OUT_MAIN, 3, 0, 0),199	F(307200000, P_DISP_CC_PLL0_OUT_MAIN, 2.5, 0, 0),200	F(384000000, P_DISP_CC_PLL0_OUT_MAIN, 2, 0, 0),201	{ }202};203 204static struct clk_rcg2 disp_cc_mdss_mdp_clk_src = {205	.cmd_rcgr = 0x2074,206	.mnd_width = 0,207	.hid_width = 5,208	.parent_map = disp_cc_parent_map_3,209	.freq_tbl = ftbl_disp_cc_mdss_mdp_clk_src,210	.clkr.hw.init = &(struct clk_init_data){211		.name = "disp_cc_mdss_mdp_clk_src",212		.parent_data = disp_cc_parent_data_3,213		.num_parents = ARRAY_SIZE(disp_cc_parent_data_3),214		.flags = CLK_SET_RATE_PARENT,215		.ops = &clk_rcg2_shared_ops,216	},217};218 219static struct clk_rcg2 disp_cc_mdss_pclk0_clk_src = {220	.cmd_rcgr = 0x205c,221	.mnd_width = 8,222	.hid_width = 5,223	.parent_map = disp_cc_parent_map_4,224	.clkr.hw.init = &(struct clk_init_data){225		.name = "disp_cc_mdss_pclk0_clk_src",226		.parent_data = disp_cc_parent_data_4,227		.num_parents = ARRAY_SIZE(disp_cc_parent_data_4),228		/* For set_rate and set_parent to succeed, parent(s) must be enabled */229		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,230		.ops = &clk_pixel_ops,231	},232};233 234static struct clk_rcg2 disp_cc_mdss_vsync_clk_src = {235	.cmd_rcgr = 0x208c,236	.mnd_width = 0,237	.hid_width = 5,238	.parent_map = disp_cc_parent_map_1,239	.freq_tbl = ftbl_disp_cc_mdss_esc0_clk_src,240	.clkr.hw.init = &(struct clk_init_data){241		.name = "disp_cc_mdss_vsync_clk_src",242		.parent_data = disp_cc_parent_data_1,243		.num_parents = ARRAY_SIZE(disp_cc_parent_data_1),244		.flags = CLK_SET_RATE_PARENT,245		.ops = &clk_rcg2_shared_ops,246	},247};248 249static const struct freq_tbl ftbl_disp_cc_sleep_clk_src[] = {250	F(32764, P_SLEEP_CLK, 1, 0, 0),251	{ }252};253 254static struct clk_rcg2 disp_cc_sleep_clk_src = {255	.cmd_rcgr = 0x6050,256	.mnd_width = 0,257	.hid_width = 5,258	.parent_map = disp_cc_parent_map_5,259	.freq_tbl = ftbl_disp_cc_sleep_clk_src,260	.clkr.hw.init = &(struct clk_init_data){261		.name = "disp_cc_sleep_clk_src",262		.parent_data = disp_cc_parent_data_5,263		.num_parents = ARRAY_SIZE(disp_cc_parent_data_5),264		.ops = &clk_rcg2_ops,265	},266};267 268static struct clk_branch disp_cc_mdss_ahb_clk = {269	.halt_reg = 0x2044,270	.halt_check = BRANCH_HALT,271	.clkr = {272		.enable_reg = 0x2044,273		.enable_mask = BIT(0),274		.hw.init = &(struct clk_init_data){275			.name = "disp_cc_mdss_ahb_clk",276			.parent_hws = (const struct clk_hw*[]){277				&disp_cc_mdss_ahb_clk_src.clkr.hw,278			},279			.num_parents = 1,280			.flags = CLK_SET_RATE_PARENT,281			.ops = &clk_branch2_ops,282		},283	},284};285 286static struct clk_branch disp_cc_mdss_byte0_clk = {287	.halt_reg = 0x201c,288	.halt_check = BRANCH_HALT,289	.clkr = {290		.enable_reg = 0x201c,291		.enable_mask = BIT(0),292		.hw.init = &(struct clk_init_data){293			.name = "disp_cc_mdss_byte0_clk",294			.parent_hws = (const struct clk_hw*[]){295				&disp_cc_mdss_byte0_clk_src.clkr.hw,296			},297			.num_parents = 1,298			.flags = CLK_SET_RATE_PARENT,299			.ops = &clk_branch2_ops,300		},301	},302};303 304static struct clk_branch disp_cc_mdss_byte0_intf_clk = {305	.halt_reg = 0x2020,306	.halt_check = BRANCH_HALT,307	.clkr = {308		.enable_reg = 0x2020,309		.enable_mask = BIT(0),310		.hw.init = &(struct clk_init_data){311			.name = "disp_cc_mdss_byte0_intf_clk",312			.parent_hws = (const struct clk_hw*[]){313				&disp_cc_mdss_byte0_div_clk_src.clkr.hw,314			},315			.num_parents = 1,316			.flags = CLK_SET_RATE_PARENT,317			.ops = &clk_branch2_ops,318		},319	},320};321 322static struct clk_branch disp_cc_mdss_esc0_clk = {323	.halt_reg = 0x2024,324	.halt_check = BRANCH_HALT,325	.clkr = {326		.enable_reg = 0x2024,327		.enable_mask = BIT(0),328		.hw.init = &(struct clk_init_data){329			.name = "disp_cc_mdss_esc0_clk",330			.parent_hws = (const struct clk_hw*[]){331				&disp_cc_mdss_esc0_clk_src.clkr.hw,332			},333			.num_parents = 1,334			.flags = CLK_SET_RATE_PARENT,335			.ops = &clk_branch2_ops,336		},337	},338};339 340static struct clk_branch disp_cc_mdss_mdp_clk = {341	.halt_reg = 0x2008,342	.halt_check = BRANCH_HALT,343	.clkr = {344		.enable_reg = 0x2008,345		.enable_mask = BIT(0),346		.hw.init = &(struct clk_init_data){347			.name = "disp_cc_mdss_mdp_clk",348			.parent_hws = (const struct clk_hw*[]){349				&disp_cc_mdss_mdp_clk_src.clkr.hw,350			},351			.num_parents = 1,352			.flags = CLK_SET_RATE_PARENT,353			.ops = &clk_branch2_ops,354		},355	},356};357 358static struct clk_branch disp_cc_mdss_mdp_lut_clk = {359	.halt_reg = 0x2010,360	.halt_check = BRANCH_HALT_VOTED,361	.clkr = {362		.enable_reg = 0x2010,363		.enable_mask = BIT(0),364		.hw.init = &(struct clk_init_data){365			.name = "disp_cc_mdss_mdp_lut_clk",366			.parent_hws = (const struct clk_hw*[]){367				&disp_cc_mdss_mdp_clk_src.clkr.hw,368			},369			.num_parents = 1,370			.flags = CLK_SET_RATE_PARENT,371			.ops = &clk_branch2_ops,372		},373	},374};375 376static struct clk_branch disp_cc_mdss_non_gdsc_ahb_clk = {377	.halt_reg = 0x4004,378	.halt_check = BRANCH_HALT_VOTED,379	.clkr = {380		.enable_reg = 0x4004,381		.enable_mask = BIT(0),382		.hw.init = &(struct clk_init_data){383			.name = "disp_cc_mdss_non_gdsc_ahb_clk",384			.parent_hws = (const struct clk_hw*[]){385				&disp_cc_mdss_ahb_clk_src.clkr.hw,386			},387			.num_parents = 1,388			.flags = CLK_SET_RATE_PARENT,389			.ops = &clk_branch2_ops,390		},391	},392};393 394static struct clk_branch disp_cc_mdss_pclk0_clk = {395	.halt_reg = 0x2004,396	.halt_check = BRANCH_HALT,397	.clkr = {398		.enable_reg = 0x2004,399		.enable_mask = BIT(0),400		.hw.init = &(struct clk_init_data){401			.name = "disp_cc_mdss_pclk0_clk",402			.parent_hws = (const struct clk_hw*[]){403				&disp_cc_mdss_pclk0_clk_src.clkr.hw,404			},405			.num_parents = 1,406			.flags = CLK_SET_RATE_PARENT,407			.ops = &clk_branch2_ops,408		},409	},410};411 412static struct clk_branch disp_cc_mdss_vsync_clk = {413	.halt_reg = 0x2018,414	.halt_check = BRANCH_HALT,415	.clkr = {416		.enable_reg = 0x2018,417		.enable_mask = BIT(0),418		.hw.init = &(struct clk_init_data){419			.name = "disp_cc_mdss_vsync_clk",420			.parent_hws = (const struct clk_hw*[]){421				&disp_cc_mdss_vsync_clk_src.clkr.hw,422			},423			.num_parents = 1,424			.flags = CLK_SET_RATE_PARENT,425			.ops = &clk_branch2_ops,426		},427	},428};429 430static struct clk_branch disp_cc_sleep_clk = {431	.halt_reg = 0x6068,432	.halt_check = BRANCH_HALT,433	.clkr = {434		.enable_reg = 0x6068,435		.enable_mask = BIT(0),436		.hw.init = &(struct clk_init_data){437			.name = "disp_cc_sleep_clk",438			.parent_hws = (const struct clk_hw*[]){439				&disp_cc_sleep_clk_src.clkr.hw,440			},441			.num_parents = 1,442			.flags = CLK_SET_RATE_PARENT,443			.ops = &clk_branch2_ops,444		},445	},446};447 448static const struct qcom_reset_map disp_cc_qcm2290_resets[] = {449	[DISP_CC_MDSS_CORE_BCR] = { 0x2000 },450};451 452static struct gdsc mdss_gdsc = {453	.gdscr = 0x3000,454	.pd = {455		.name = "mdss_gdsc",456	},457	.pwrsts = PWRSTS_OFF_ON,458	.flags = HW_CTRL,459};460 461static struct gdsc *disp_cc_qcm2290_gdscs[] = {462	[MDSS_GDSC] = &mdss_gdsc,463};464 465static struct clk_regmap *disp_cc_qcm2290_clocks[] = {466	[DISP_CC_MDSS_AHB_CLK] = &disp_cc_mdss_ahb_clk.clkr,467	[DISP_CC_MDSS_AHB_CLK_SRC] = &disp_cc_mdss_ahb_clk_src.clkr,468	[DISP_CC_MDSS_BYTE0_CLK] = &disp_cc_mdss_byte0_clk.clkr,469	[DISP_CC_MDSS_BYTE0_CLK_SRC] = &disp_cc_mdss_byte0_clk_src.clkr,470	[DISP_CC_MDSS_BYTE0_DIV_CLK_SRC] = &disp_cc_mdss_byte0_div_clk_src.clkr,471	[DISP_CC_MDSS_BYTE0_INTF_CLK] = &disp_cc_mdss_byte0_intf_clk.clkr,472	[DISP_CC_MDSS_ESC0_CLK] = &disp_cc_mdss_esc0_clk.clkr,473	[DISP_CC_MDSS_ESC0_CLK_SRC] = &disp_cc_mdss_esc0_clk_src.clkr,474	[DISP_CC_MDSS_MDP_CLK] = &disp_cc_mdss_mdp_clk.clkr,475	[DISP_CC_MDSS_MDP_CLK_SRC] = &disp_cc_mdss_mdp_clk_src.clkr,476	[DISP_CC_MDSS_MDP_LUT_CLK] = &disp_cc_mdss_mdp_lut_clk.clkr,477	[DISP_CC_MDSS_NON_GDSC_AHB_CLK] = &disp_cc_mdss_non_gdsc_ahb_clk.clkr,478	[DISP_CC_MDSS_PCLK0_CLK] = &disp_cc_mdss_pclk0_clk.clkr,479	[DISP_CC_MDSS_PCLK0_CLK_SRC] = &disp_cc_mdss_pclk0_clk_src.clkr,480	[DISP_CC_MDSS_VSYNC_CLK] = &disp_cc_mdss_vsync_clk.clkr,481	[DISP_CC_MDSS_VSYNC_CLK_SRC] = &disp_cc_mdss_vsync_clk_src.clkr,482	[DISP_CC_PLL0] = &disp_cc_pll0.clkr,483	[DISP_CC_SLEEP_CLK] = &disp_cc_sleep_clk.clkr,484	[DISP_CC_SLEEP_CLK_SRC] = &disp_cc_sleep_clk_src.clkr,485};486 487static const struct regmap_config disp_cc_qcm2290_regmap_config = {488	.reg_bits = 32,489	.reg_stride = 4,490	.val_bits = 32,491	.max_register = 0x10000,492	.fast_io = true,493};494 495static const struct qcom_cc_desc disp_cc_qcm2290_desc = {496	.config = &disp_cc_qcm2290_regmap_config,497	.clks = disp_cc_qcm2290_clocks,498	.num_clks = ARRAY_SIZE(disp_cc_qcm2290_clocks),499	.gdscs = disp_cc_qcm2290_gdscs,500	.num_gdscs = ARRAY_SIZE(disp_cc_qcm2290_gdscs),501	.resets = disp_cc_qcm2290_resets,502	.num_resets = ARRAY_SIZE(disp_cc_qcm2290_resets),503};504 505static const struct of_device_id disp_cc_qcm2290_match_table[] = {506	{ .compatible = "qcom,qcm2290-dispcc" },507	{ }508};509MODULE_DEVICE_TABLE(of, disp_cc_qcm2290_match_table);510 511static int disp_cc_qcm2290_probe(struct platform_device *pdev)512{513	struct regmap *regmap;514	int ret;515 516	regmap = qcom_cc_map(pdev, &disp_cc_qcm2290_desc);517	if (IS_ERR(regmap))518		return PTR_ERR(regmap);519 520	clk_alpha_pll_configure(&disp_cc_pll0, regmap, &disp_cc_pll0_config);521 522	/* Keep some clocks always-on */523	qcom_branch_set_clk_en(regmap, 0x604c); /* DISP_CC_XO_CLK */524 525	ret = qcom_cc_really_probe(&pdev->dev, &disp_cc_qcm2290_desc, regmap);526	if (ret) {527		dev_err(&pdev->dev, "Failed to register DISP CC clocks\n");528		return ret;529	}530 531	return ret;532}533 534static struct platform_driver disp_cc_qcm2290_driver = {535	.probe = disp_cc_qcm2290_probe,536	.driver = {537		.name = "dispcc-qcm2290",538		.of_match_table = disp_cc_qcm2290_match_table,539	},540};541 542module_platform_driver(disp_cc_qcm2290_driver);543 544MODULE_DESCRIPTION("QTI DISP_CC qcm2290 Driver");545MODULE_LICENSE("GPL v2");546