cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

gpucc-msm8998.c (8741B)


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