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

lcc-ipq806x.c (10073B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
      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
     16#include <dt-bindings/clock/qcom,lcc-ipq806x.h>
     17
     18#include "common.h"
     19#include "clk-regmap.h"
     20#include "clk-pll.h"
     21#include "clk-rcg.h"
     22#include "clk-branch.h"
     23#include "clk-regmap-divider.h"
     24#include "clk-regmap-mux.h"
     25
     26static struct clk_pll pll4 = {
     27	.l_reg = 0x4,
     28	.m_reg = 0x8,
     29	.n_reg = 0xc,
     30	.config_reg = 0x14,
     31	.mode_reg = 0x0,
     32	.status_reg = 0x18,
     33	.status_bit = 16,
     34	.clkr.hw.init = &(struct clk_init_data){
     35		.name = "pll4",
     36		.parent_names = (const char *[]){ "pxo" },
     37		.num_parents = 1,
     38		.ops = &clk_pll_ops,
     39	},
     40};
     41
     42static const struct pll_config pll4_config = {
     43	.l = 0xf,
     44	.m = 0x91,
     45	.n = 0xc7,
     46	.vco_val = 0x0,
     47	.vco_mask = BIT(17) | BIT(16),
     48	.pre_div_val = 0x0,
     49	.pre_div_mask = BIT(19),
     50	.post_div_val = 0x0,
     51	.post_div_mask = BIT(21) | BIT(20),
     52	.mn_ena_mask = BIT(22),
     53	.main_output_mask = BIT(23),
     54};
     55
     56enum {
     57	P_PXO,
     58	P_PLL4,
     59};
     60
     61static const struct parent_map lcc_pxo_pll4_map[] = {
     62	{ P_PXO, 0 },
     63	{ P_PLL4, 2 }
     64};
     65
     66static const char * const lcc_pxo_pll4[] = {
     67	"pxo",
     68	"pll4_vote",
     69};
     70
     71static struct freq_tbl clk_tbl_aif_mi2s[] = {
     72	{  1024000, P_PLL4, 4,  1,  96 },
     73	{  1411200, P_PLL4, 4,  2, 139 },
     74	{  1536000, P_PLL4, 4,  1,  64 },
     75	{  2048000, P_PLL4, 4,  1,  48 },
     76	{  2116800, P_PLL4, 4,  2,  93 },
     77	{  2304000, P_PLL4, 4,  2,  85 },
     78	{  2822400, P_PLL4, 4,  6, 209 },
     79	{  3072000, P_PLL4, 4,  1,  32 },
     80	{  3175200, P_PLL4, 4,  1,  31 },
     81	{  4096000, P_PLL4, 4,  1,  24 },
     82	{  4233600, P_PLL4, 4,  9, 209 },
     83	{  4608000, P_PLL4, 4,  3,  64 },
     84	{  5644800, P_PLL4, 4, 12, 209 },
     85	{  6144000, P_PLL4, 4,  1,  16 },
     86	{  6350400, P_PLL4, 4,  2,  31 },
     87	{  8192000, P_PLL4, 4,  1,  12 },
     88	{  8467200, P_PLL4, 4, 18, 209 },
     89	{  9216000, P_PLL4, 4,  3,  32 },
     90	{ 11289600, P_PLL4, 4, 24, 209 },
     91	{ 12288000, P_PLL4, 4,  1,   8 },
     92	{ 12700800, P_PLL4, 4, 27, 209 },
     93	{ 13824000, P_PLL4, 4,  9,  64 },
     94	{ 16384000, P_PLL4, 4,  1,   6 },
     95	{ 16934400, P_PLL4, 4, 41, 238 },
     96	{ 18432000, P_PLL4, 4,  3,  16 },
     97	{ 22579200, P_PLL4, 2, 24, 209 },
     98	{ 24576000, P_PLL4, 4,  1,   4 },
     99	{ 27648000, P_PLL4, 4,  9,  32 },
    100	{ 33868800, P_PLL4, 4, 41, 119 },
    101	{ 36864000, P_PLL4, 4,  3,   8 },
    102	{ 45158400, P_PLL4, 1, 24, 209 },
    103	{ 49152000, P_PLL4, 4,  1,   2 },
    104	{ 50803200, P_PLL4, 1, 27, 209 },
    105	{ }
    106};
    107
    108static struct clk_rcg mi2s_osr_src = {
    109	.ns_reg = 0x48,
    110	.md_reg = 0x4c,
    111	.mn = {
    112		.mnctr_en_bit = 8,
    113		.mnctr_reset_bit = 7,
    114		.mnctr_mode_shift = 5,
    115		.n_val_shift = 24,
    116		.m_val_shift = 8,
    117		.width = 8,
    118	},
    119	.p = {
    120		.pre_div_shift = 3,
    121		.pre_div_width = 2,
    122	},
    123	.s = {
    124		.src_sel_shift = 0,
    125		.parent_map = lcc_pxo_pll4_map,
    126	},
    127	.freq_tbl = clk_tbl_aif_mi2s,
    128	.clkr = {
    129		.enable_reg = 0x48,
    130		.enable_mask = BIT(9),
    131		.hw.init = &(struct clk_init_data){
    132			.name = "mi2s_osr_src",
    133			.parent_names = lcc_pxo_pll4,
    134			.num_parents = 2,
    135			.ops = &clk_rcg_ops,
    136			.flags = CLK_SET_RATE_GATE,
    137		},
    138	},
    139};
    140
    141static const char * const lcc_mi2s_parents[] = {
    142	"mi2s_osr_src",
    143};
    144
    145static struct clk_branch mi2s_osr_clk = {
    146	.halt_reg = 0x50,
    147	.halt_bit = 1,
    148	.halt_check = BRANCH_HALT_ENABLE,
    149	.clkr = {
    150		.enable_reg = 0x48,
    151		.enable_mask = BIT(17),
    152		.hw.init = &(struct clk_init_data){
    153			.name = "mi2s_osr_clk",
    154			.parent_names = lcc_mi2s_parents,
    155			.num_parents = 1,
    156			.ops = &clk_branch_ops,
    157			.flags = CLK_SET_RATE_PARENT,
    158		},
    159	},
    160};
    161
    162static struct clk_regmap_div mi2s_div_clk = {
    163	.reg = 0x48,
    164	.shift = 10,
    165	.width = 4,
    166	.clkr = {
    167		.hw.init = &(struct clk_init_data){
    168			.name = "mi2s_div_clk",
    169			.parent_names = lcc_mi2s_parents,
    170			.num_parents = 1,
    171			.ops = &clk_regmap_div_ops,
    172		},
    173	},
    174};
    175
    176static struct clk_branch mi2s_bit_div_clk = {
    177	.halt_reg = 0x50,
    178	.halt_bit = 0,
    179	.halt_check = BRANCH_HALT_ENABLE,
    180	.clkr = {
    181		.enable_reg = 0x48,
    182		.enable_mask = BIT(15),
    183		.hw.init = &(struct clk_init_data){
    184			.name = "mi2s_bit_div_clk",
    185			.parent_names = (const char *[]){ "mi2s_div_clk" },
    186			.num_parents = 1,
    187			.ops = &clk_branch_ops,
    188			.flags = CLK_SET_RATE_PARENT,
    189		},
    190	},
    191};
    192
    193
    194static struct clk_regmap_mux mi2s_bit_clk = {
    195	.reg = 0x48,
    196	.shift = 14,
    197	.width = 1,
    198	.clkr = {
    199		.hw.init = &(struct clk_init_data){
    200			.name = "mi2s_bit_clk",
    201			.parent_names = (const char *[]){
    202				"mi2s_bit_div_clk",
    203				"mi2s_codec_clk",
    204			},
    205			.num_parents = 2,
    206			.ops = &clk_regmap_mux_closest_ops,
    207			.flags = CLK_SET_RATE_PARENT,
    208		},
    209	},
    210};
    211
    212static struct freq_tbl clk_tbl_pcm[] = {
    213	{   64000, P_PLL4, 4, 1, 1536 },
    214	{  128000, P_PLL4, 4, 1,  768 },
    215	{  256000, P_PLL4, 4, 1,  384 },
    216	{  512000, P_PLL4, 4, 1,  192 },
    217	{ 1024000, P_PLL4, 4, 1,   96 },
    218	{ 2048000, P_PLL4, 4, 1,   48 },
    219	{ },
    220};
    221
    222static struct clk_rcg pcm_src = {
    223	.ns_reg = 0x54,
    224	.md_reg = 0x58,
    225	.mn = {
    226		.mnctr_en_bit = 8,
    227		.mnctr_reset_bit = 7,
    228		.mnctr_mode_shift = 5,
    229		.n_val_shift = 16,
    230		.m_val_shift = 16,
    231		.width = 16,
    232	},
    233	.p = {
    234		.pre_div_shift = 3,
    235		.pre_div_width = 2,
    236	},
    237	.s = {
    238		.src_sel_shift = 0,
    239		.parent_map = lcc_pxo_pll4_map,
    240	},
    241	.freq_tbl = clk_tbl_pcm,
    242	.clkr = {
    243		.enable_reg = 0x54,
    244		.enable_mask = BIT(9),
    245		.hw.init = &(struct clk_init_data){
    246			.name = "pcm_src",
    247			.parent_names = lcc_pxo_pll4,
    248			.num_parents = 2,
    249			.ops = &clk_rcg_ops,
    250			.flags = CLK_SET_RATE_GATE,
    251		},
    252	},
    253};
    254
    255static struct clk_branch pcm_clk_out = {
    256	.halt_reg = 0x5c,
    257	.halt_bit = 0,
    258	.halt_check = BRANCH_HALT_ENABLE,
    259	.clkr = {
    260		.enable_reg = 0x54,
    261		.enable_mask = BIT(11),
    262		.hw.init = &(struct clk_init_data){
    263			.name = "pcm_clk_out",
    264			.parent_names = (const char *[]){ "pcm_src" },
    265			.num_parents = 1,
    266			.ops = &clk_branch_ops,
    267			.flags = CLK_SET_RATE_PARENT,
    268		},
    269	},
    270};
    271
    272static struct clk_regmap_mux pcm_clk = {
    273	.reg = 0x54,
    274	.shift = 10,
    275	.width = 1,
    276	.clkr = {
    277		.hw.init = &(struct clk_init_data){
    278			.name = "pcm_clk",
    279			.parent_names = (const char *[]){
    280				"pcm_clk_out",
    281				"pcm_codec_clk",
    282			},
    283			.num_parents = 2,
    284			.ops = &clk_regmap_mux_closest_ops,
    285			.flags = CLK_SET_RATE_PARENT,
    286		},
    287	},
    288};
    289
    290static struct freq_tbl clk_tbl_aif_osr[] = {
    291	{  2822400, P_PLL4, 1, 147, 20480 },
    292	{  4096000, P_PLL4, 1,   1,    96 },
    293	{  5644800, P_PLL4, 1, 147, 10240 },
    294	{  6144000, P_PLL4, 1,   1,    64 },
    295	{ 11289600, P_PLL4, 1, 147,  5120 },
    296	{ 12288000, P_PLL4, 1,   1,    32 },
    297	{ 22579200, P_PLL4, 1, 147,  2560 },
    298	{ 24576000, P_PLL4, 1,   1,    16 },
    299	{ },
    300};
    301
    302static struct clk_rcg spdif_src = {
    303	.ns_reg = 0xcc,
    304	.md_reg = 0xd0,
    305	.mn = {
    306		.mnctr_en_bit = 8,
    307		.mnctr_reset_bit = 7,
    308		.mnctr_mode_shift = 5,
    309		.n_val_shift = 16,
    310		.m_val_shift = 16,
    311		.width = 8,
    312	},
    313	.p = {
    314		.pre_div_shift = 3,
    315		.pre_div_width = 2,
    316	},
    317	.s = {
    318		.src_sel_shift = 0,
    319		.parent_map = lcc_pxo_pll4_map,
    320	},
    321	.freq_tbl = clk_tbl_aif_osr,
    322	.clkr = {
    323		.enable_reg = 0xcc,
    324		.enable_mask = BIT(9),
    325		.hw.init = &(struct clk_init_data){
    326			.name = "spdif_src",
    327			.parent_names = lcc_pxo_pll4,
    328			.num_parents = 2,
    329			.ops = &clk_rcg_ops,
    330			.flags = CLK_SET_RATE_GATE,
    331		},
    332	},
    333};
    334
    335static const char * const lcc_spdif_parents[] = {
    336	"spdif_src",
    337};
    338
    339static struct clk_branch spdif_clk = {
    340	.halt_reg = 0xd4,
    341	.halt_bit = 1,
    342	.halt_check = BRANCH_HALT_ENABLE,
    343	.clkr = {
    344		.enable_reg = 0xcc,
    345		.enable_mask = BIT(12),
    346		.hw.init = &(struct clk_init_data){
    347			.name = "spdif_clk",
    348			.parent_names = lcc_spdif_parents,
    349			.num_parents = 1,
    350			.ops = &clk_branch_ops,
    351			.flags = CLK_SET_RATE_PARENT,
    352		},
    353	},
    354};
    355
    356static struct freq_tbl clk_tbl_ahbix[] = {
    357	{ 131072000, P_PLL4, 1, 1, 3 },
    358	{ },
    359};
    360
    361static struct clk_rcg ahbix_clk = {
    362	.ns_reg = 0x38,
    363	.md_reg = 0x3c,
    364	.mn = {
    365		.mnctr_en_bit = 8,
    366		.mnctr_reset_bit = 7,
    367		.mnctr_mode_shift = 5,
    368		.n_val_shift = 24,
    369		.m_val_shift = 8,
    370		.width = 8,
    371	},
    372	.p = {
    373		.pre_div_shift = 3,
    374		.pre_div_width = 2,
    375	},
    376	.s = {
    377		.src_sel_shift = 0,
    378		.parent_map = lcc_pxo_pll4_map,
    379	},
    380	.freq_tbl = clk_tbl_ahbix,
    381	.clkr = {
    382		.enable_reg = 0x38,
    383		.enable_mask = BIT(11),
    384		.hw.init = &(struct clk_init_data){
    385			.name = "ahbix",
    386			.parent_names = lcc_pxo_pll4,
    387			.num_parents = 2,
    388			.ops = &clk_rcg_lcc_ops,
    389		},
    390	},
    391};
    392
    393static struct clk_regmap *lcc_ipq806x_clks[] = {
    394	[PLL4] = &pll4.clkr,
    395	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
    396	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
    397	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
    398	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
    399	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
    400	[PCM_SRC] = &pcm_src.clkr,
    401	[PCM_CLK_OUT] = &pcm_clk_out.clkr,
    402	[PCM_CLK] = &pcm_clk.clkr,
    403	[SPDIF_SRC] = &spdif_src.clkr,
    404	[SPDIF_CLK] = &spdif_clk.clkr,
    405	[AHBIX_CLK] = &ahbix_clk.clkr,
    406};
    407
    408static const struct regmap_config lcc_ipq806x_regmap_config = {
    409	.reg_bits	= 32,
    410	.reg_stride	= 4,
    411	.val_bits	= 32,
    412	.max_register	= 0xfc,
    413	.fast_io	= true,
    414};
    415
    416static const struct qcom_cc_desc lcc_ipq806x_desc = {
    417	.config = &lcc_ipq806x_regmap_config,
    418	.clks = lcc_ipq806x_clks,
    419	.num_clks = ARRAY_SIZE(lcc_ipq806x_clks),
    420};
    421
    422static const struct of_device_id lcc_ipq806x_match_table[] = {
    423	{ .compatible = "qcom,lcc-ipq8064" },
    424	{ }
    425};
    426MODULE_DEVICE_TABLE(of, lcc_ipq806x_match_table);
    427
    428static int lcc_ipq806x_probe(struct platform_device *pdev)
    429{
    430	u32 val;
    431	struct regmap *regmap;
    432
    433	regmap = qcom_cc_map(pdev, &lcc_ipq806x_desc);
    434	if (IS_ERR(regmap))
    435		return PTR_ERR(regmap);
    436
    437	/* Configure the rate of PLL4 if the bootloader hasn't already */
    438	regmap_read(regmap, 0x0, &val);
    439	if (!val)
    440		clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
    441	/* Enable PLL4 source on the LPASS Primary PLL Mux */
    442	regmap_write(regmap, 0xc4, 0x1);
    443
    444	return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
    445}
    446
    447static struct platform_driver lcc_ipq806x_driver = {
    448	.probe		= lcc_ipq806x_probe,
    449	.driver		= {
    450		.name	= "lcc-ipq806x",
    451		.of_match_table = lcc_ipq806x_match_table,
    452	},
    453};
    454module_platform_driver(lcc_ipq806x_driver);
    455
    456MODULE_DESCRIPTION("QCOM LCC IPQ806x Driver");
    457MODULE_LICENSE("GPL v2");
    458MODULE_ALIAS("platform:lcc-ipq806x");