brintos

brintos / linux-shallow public Read only

0
0
Text · 8.5 KiB · 9efeab2 Raw
351 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Copyright (c) 2019, Jeffrey Hugo4 */5 6#include <linux/kernel.h>7#include <linux/bitops.h>8#include <linux/err.h>9#include <linux/platform_device.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/clk-provider.h>13#include <linux/regmap.h>14#include <linux/reset-controller.h>15 16#include <dt-bindings/clock/qcom,gpucc-msm8998.h>17 18#include "common.h"19#include "clk-regmap.h"20#include "clk-regmap-divider.h"21#include "clk-alpha-pll.h"22#include "clk-rcg.h"23#include "clk-branch.h"24#include "reset.h"25#include "gdsc.h"26 27enum {28	P_XO,29	P_GPLL0,30	P_GPUPLL0_OUT_EVEN,31};32 33/* Instead of going directly to the block, XO is routed through this branch */34static struct clk_branch gpucc_cxo_clk = {35	.halt_reg = 0x1020,36	.clkr = {37		.enable_reg = 0x1020,38		.enable_mask = BIT(0),39		.hw.init = &(struct clk_init_data){40			.name = "gpucc_cxo_clk",41			.parent_data = &(const struct clk_parent_data){42				.fw_name = "xo"43			},44			.num_parents = 1,45			.ops = &clk_branch2_ops,46			.flags = CLK_IS_CRITICAL,47		},48	},49};50 51static const struct pll_vco fabia_vco[] = {52	{ 249600000, 2000000000, 0 },53	{ 125000000, 1000000000, 1 },54};55 56static const struct clk_div_table post_div_table_fabia_even[] = {57	{ 0x0, 1 },58	{ 0x1, 2 },59	{ 0x3, 4 },60	{ 0x7, 8 },61	{ }62};63 64static struct clk_alpha_pll gpupll0 = {65	.offset = 0x0,66	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],67	.vco_table = fabia_vco,68	.num_vco = ARRAY_SIZE(fabia_vco),69	.clkr.hw.init = &(struct clk_init_data){70		.name = "gpupll0",71		.parent_hws = (const struct clk_hw *[]){ &gpucc_cxo_clk.clkr.hw },72		.num_parents = 1,73		.ops = &clk_alpha_pll_fabia_ops,74	},75};76 77static struct clk_alpha_pll_postdiv gpupll0_out_even = {78	.offset = 0x0,79	.post_div_shift = 8,80	.post_div_table = post_div_table_fabia_even,81	.num_post_div = ARRAY_SIZE(post_div_table_fabia_even),82	.width = 4,83	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA],84	.clkr.hw.init = &(struct clk_init_data){85		.name = "gpupll0_out_even",86		.parent_hws = (const struct clk_hw *[]){ &gpupll0.clkr.hw },87		.num_parents = 1,88		.flags = CLK_SET_RATE_PARENT,89		.ops = &clk_alpha_pll_postdiv_fabia_ops,90	},91};92 93static const struct parent_map gpu_xo_gpll0_map[] = {94	{ P_XO, 0 },95	{ P_GPLL0, 5 },96};97 98static const struct clk_parent_data gpu_xo_gpll0[] = {99	{ .hw = &gpucc_cxo_clk.clkr.hw },100	{ .fw_name = "gpll0", .name = "gcc_gpu_gpll0_clk" },101};102 103static const struct parent_map gpu_xo_gpupll0_map[] = {104	{ P_XO, 0 },105	{ P_GPUPLL0_OUT_EVEN, 1 },106};107 108static const struct clk_hw *gpu_xo_gpupll0[] = {109	&gpucc_cxo_clk.clkr.hw,110	&gpupll0_out_even.clkr.hw,111};112 113static const struct freq_tbl ftbl_rbcpr_clk_src[] = {114	F(19200000, P_XO, 1, 0, 0),115	F(50000000, P_GPLL0, 12, 0, 0),116	{ }117};118 119static struct clk_rcg2 rbcpr_clk_src = {120	.cmd_rcgr = 0x1030,121	.hid_width = 5,122	.parent_map = gpu_xo_gpll0_map,123	.freq_tbl = ftbl_rbcpr_clk_src,124	.clkr.hw.init = &(struct clk_init_data){125		.name = "rbcpr_clk_src",126		.parent_data = gpu_xo_gpll0,127		.num_parents = ARRAY_SIZE(gpu_xo_gpll0),128		.ops = &clk_rcg2_ops,129	},130};131 132static const struct freq_tbl ftbl_gfx3d_clk_src[] = {133	{ .src = P_GPUPLL0_OUT_EVEN, .pre_div = 3 },134	{ }135};136 137static struct clk_rcg2 gfx3d_clk_src = {138	.cmd_rcgr = 0x1070,139	.hid_width = 5,140	.parent_map = gpu_xo_gpupll0_map,141	.freq_tbl = ftbl_gfx3d_clk_src,142	.clkr.hw.init = &(struct clk_init_data){143		.name = "gfx3d_clk_src",144		.parent_hws = gpu_xo_gpupll0,145		.num_parents = ARRAY_SIZE(gpu_xo_gpupll0),146		.ops = &clk_rcg2_ops,147		.flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE,148	},149};150 151static const struct freq_tbl ftbl_rbbmtimer_clk_src[] = {152	F(19200000, P_XO, 1, 0, 0),153	{ }154};155 156static struct clk_rcg2 rbbmtimer_clk_src = {157	.cmd_rcgr = 0x10b0,158	.hid_width = 5,159	.parent_map = gpu_xo_gpll0_map,160	.freq_tbl = ftbl_rbbmtimer_clk_src,161	.clkr.hw.init = &(struct clk_init_data){162		.name = "rbbmtimer_clk_src",163		.parent_data = gpu_xo_gpll0,164		.num_parents = ARRAY_SIZE(gpu_xo_gpll0),165		.ops = &clk_rcg2_ops,166	},167};168 169static const struct freq_tbl ftbl_gfx3d_isense_clk_src[] = {170	F(19200000, P_XO, 1, 0, 0),171	F(40000000, P_GPLL0, 15, 0, 0),172	F(200000000, P_GPLL0, 3, 0, 0),173	F(300000000, P_GPLL0, 2, 0, 0),174	{ }175};176 177static struct clk_rcg2 gfx3d_isense_clk_src = {178	.cmd_rcgr = 0x1100,179	.hid_width = 5,180	.parent_map = gpu_xo_gpll0_map,181	.freq_tbl = ftbl_gfx3d_isense_clk_src,182	.clkr.hw.init = &(struct clk_init_data){183		.name = "gfx3d_isense_clk_src",184		.parent_data = gpu_xo_gpll0,185		.num_parents = ARRAY_SIZE(gpu_xo_gpll0),186		.ops = &clk_rcg2_ops,187	},188};189 190static struct clk_branch rbcpr_clk = {191	.halt_reg = 0x1054,192	.clkr = {193		.enable_reg = 0x1054,194		.enable_mask = BIT(0),195		.hw.init = &(struct clk_init_data){196			.name = "rbcpr_clk",197			.parent_hws = (const struct clk_hw *[]){ &rbcpr_clk_src.clkr.hw },198			.num_parents = 1,199			.ops = &clk_branch2_ops,200			.flags = CLK_SET_RATE_PARENT,201		},202	},203};204 205static struct clk_branch gfx3d_clk = {206	.halt_reg = 0x1098,207	.clkr = {208		.enable_reg = 0x1098,209		.enable_mask = BIT(0),210		.hw.init = &(struct clk_init_data){211			.name = "gfx3d_clk",212			.parent_hws = (const struct clk_hw *[]){ &gfx3d_clk_src.clkr.hw },213			.num_parents = 1,214			.ops = &clk_branch2_ops,215			.flags = CLK_SET_RATE_PARENT,216		},217	},218};219 220static struct clk_branch rbbmtimer_clk = {221	.halt_reg = 0x10d0,222	.clkr = {223		.enable_reg = 0x10d0,224		.enable_mask = BIT(0),225		.hw.init = &(struct clk_init_data){226			.name = "rbbmtimer_clk",227			.parent_hws = (const struct clk_hw *[]){ &rbbmtimer_clk_src.clkr.hw },228			.num_parents = 1,229			.ops = &clk_branch2_ops,230			.flags = CLK_SET_RATE_PARENT,231		},232	},233};234 235static struct clk_branch gfx3d_isense_clk = {236	.halt_reg = 0x1124,237	.clkr = {238		.enable_reg = 0x1124,239		.enable_mask = BIT(0),240		.hw.init = &(struct clk_init_data){241			.name = "gfx3d_isense_clk",242			.parent_hws = (const struct clk_hw *[]){ &gfx3d_isense_clk_src.clkr.hw },243			.num_parents = 1,244			.ops = &clk_branch2_ops,245		},246	},247};248 249static struct gdsc gpu_cx_gdsc = {250	.gdscr = 0x1004,251	.gds_hw_ctrl = 0x1008,252	.pd = {253		.name = "gpu_cx",254	},255	.pwrsts = PWRSTS_OFF_ON,256	.flags = VOTABLE,257};258 259static struct gdsc gpu_gx_gdsc = {260	.gdscr = 0x1094,261	.clamp_io_ctrl = 0x130,262	.resets = (unsigned int []){ GPU_GX_BCR },263	.reset_count = 1,264	.cxcs = (unsigned int []){ 0x1098 },265	.cxc_count = 1,266	.pd = {267		.name = "gpu_gx",268	},269	.parent = &gpu_cx_gdsc.pd,270	.pwrsts = PWRSTS_OFF_ON | PWRSTS_RET,271	.flags = CLAMP_IO | SW_RESET | AON_RESET | NO_RET_PERIPH,272};273 274static struct clk_regmap *gpucc_msm8998_clocks[] = {275	[GPUPLL0] = &gpupll0.clkr,276	[GPUPLL0_OUT_EVEN] = &gpupll0_out_even.clkr,277	[RBCPR_CLK_SRC] = &rbcpr_clk_src.clkr,278	[GFX3D_CLK_SRC] = &gfx3d_clk_src.clkr,279	[RBBMTIMER_CLK_SRC] = &rbbmtimer_clk_src.clkr,280	[GFX3D_ISENSE_CLK_SRC] = &gfx3d_isense_clk_src.clkr,281	[RBCPR_CLK] = &rbcpr_clk.clkr,282	[GFX3D_CLK] = &gfx3d_clk.clkr,283	[RBBMTIMER_CLK] = &rbbmtimer_clk.clkr,284	[GFX3D_ISENSE_CLK] = &gfx3d_isense_clk.clkr,285	[GPUCC_CXO_CLK] = &gpucc_cxo_clk.clkr,286};287 288static struct gdsc *gpucc_msm8998_gdscs[] = {289	[GPU_CX_GDSC] = &gpu_cx_gdsc,290	[GPU_GX_GDSC] = &gpu_gx_gdsc,291};292 293static const struct qcom_reset_map gpucc_msm8998_resets[] = {294	[GPU_CX_BCR] = { 0x1000 },295	[RBCPR_BCR] = { 0x1050 },296	[GPU_GX_BCR] = { 0x1090 },297	[GPU_ISENSE_BCR] = { 0x1120 },298};299 300static const struct regmap_config gpucc_msm8998_regmap_config = {301	.reg_bits	= 32,302	.reg_stride	= 4,303	.val_bits	= 32,304	.max_register	= 0x9000,305	.fast_io	= true,306};307 308static const struct qcom_cc_desc gpucc_msm8998_desc = {309	.config = &gpucc_msm8998_regmap_config,310	.clks = gpucc_msm8998_clocks,311	.num_clks = ARRAY_SIZE(gpucc_msm8998_clocks),312	.resets = gpucc_msm8998_resets,313	.num_resets = ARRAY_SIZE(gpucc_msm8998_resets),314	.gdscs = gpucc_msm8998_gdscs,315	.num_gdscs = ARRAY_SIZE(gpucc_msm8998_gdscs),316};317 318static const struct of_device_id gpucc_msm8998_match_table[] = {319	{ .compatible = "qcom,msm8998-gpucc" },320	{ }321};322MODULE_DEVICE_TABLE(of, gpucc_msm8998_match_table);323 324static int gpucc_msm8998_probe(struct platform_device *pdev)325{326	struct regmap *regmap;327 328	regmap = qcom_cc_map(pdev, &gpucc_msm8998_desc);329	if (IS_ERR(regmap))330		return PTR_ERR(regmap);331 332	/* force periph logic on to avoid perf counter corruption */333	regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(13), BIT(13));334	/* tweak droop detector (GPUCC_GPU_DD_WRAP_CTRL) to reduce leakage */335	regmap_write_bits(regmap, gfx3d_clk.clkr.enable_reg, BIT(0), BIT(0));336 337	return qcom_cc_really_probe(&pdev->dev, &gpucc_msm8998_desc, regmap);338}339 340static struct platform_driver gpucc_msm8998_driver = {341	.probe		= gpucc_msm8998_probe,342	.driver		= {343		.name	= "gpucc-msm8998",344		.of_match_table = gpucc_msm8998_match_table,345	},346};347module_platform_driver(gpucc_msm8998_driver);348 349MODULE_DESCRIPTION("QCOM GPUCC MSM8998 Driver");350MODULE_LICENSE("GPL v2");351