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

lpassaudiocc-sc7280.c (23959B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Copyright (c) 2021, The Linux Foundation. All rights reserved.
      4 */
      5
      6#include <linux/clk-provider.h>
      7#include <linux/err.h>
      8#include <linux/kernel.h>
      9#include <linux/module.h>
     10#include <linux/of_device.h>
     11#include <linux/pm_clock.h>
     12#include <linux/pm_runtime.h>
     13#include <linux/regmap.h>
     14
     15#include <dt-bindings/clock/qcom,lpassaudiocc-sc7280.h>
     16
     17#include "clk-alpha-pll.h"
     18#include "clk-branch.h"
     19#include "clk-rcg.h"
     20#include "clk-regmap.h"
     21#include "clk-regmap-divider.h"
     22#include "clk-regmap-mux.h"
     23#include "common.h"
     24#include "gdsc.h"
     25
     26enum {
     27	P_BI_TCXO,
     28	P_LPASS_AON_CC_PLL_OUT_EVEN,
     29	P_LPASS_AON_CC_PLL_OUT_MAIN,
     30	P_LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC,
     31	P_LPASS_AON_CC_PLL_OUT_ODD,
     32	P_LPASS_AUDIO_CC_PLL_OUT_AUX,
     33	P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC,
     34	P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK,
     35};
     36
     37static const struct pll_vco zonda_vco[] = {
     38	{ 595200000UL, 3600000000UL, 0 },
     39};
     40
     41/* 1128.96MHz configuration */
     42static const struct alpha_pll_config lpass_audio_cc_pll_config = {
     43	.l = 0x3a,
     44	.alpha = 0xcccc,
     45	.config_ctl_val = 0x08200920,
     46	.config_ctl_hi_val = 0x05002001,
     47	.config_ctl_hi1_val = 0x00000000,
     48	.user_ctl_val = 0x03000101,
     49};
     50
     51static struct clk_alpha_pll lpass_audio_cc_pll = {
     52	.offset = 0x0,
     53	.vco_table = zonda_vco,
     54	.num_vco = ARRAY_SIZE(zonda_vco),
     55	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA],
     56	.clkr = {
     57		.hw.init = &(const struct clk_init_data){
     58			.name = "lpass_audio_cc_pll",
     59			.parent_data = &(const struct clk_parent_data){
     60				.index = 0,
     61			},
     62			.num_parents = 1,
     63			.ops = &clk_alpha_pll_zonda_ops,
     64		},
     65	},
     66};
     67
     68static const struct clk_div_table post_div_table_lpass_audio_cc_pll_out_aux2[] = {
     69	{ 0x1, 2 },
     70	{ }
     71};
     72
     73static struct clk_alpha_pll_postdiv lpass_audio_cc_pll_out_aux2 = {
     74	.offset = 0x0,
     75	.post_div_shift = 8,
     76	.post_div_table = post_div_table_lpass_audio_cc_pll_out_aux2,
     77	.num_post_div = ARRAY_SIZE(post_div_table_lpass_audio_cc_pll_out_aux2),
     78	.width = 2,
     79	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_ZONDA],
     80	.clkr.hw.init = &(const struct clk_init_data){
     81		.name = "lpass_audio_cc_pll_out_aux2",
     82		.parent_hws = (const struct clk_hw*[]){
     83			&lpass_audio_cc_pll.clkr.hw,
     84		},
     85		.num_parents = 1,
     86		.ops = &clk_alpha_pll_postdiv_zonda_ops,
     87	},
     88};
     89
     90static const struct pll_vco lucid_vco[] = {
     91	{ 249600000, 2000000000, 0 },
     92};
     93
     94/* 614.4 MHz configuration */
     95static const struct alpha_pll_config lpass_aon_cc_pll_config = {
     96	.l = 0x20,
     97	.alpha = 0x0,
     98	.config_ctl_val = 0x20485699,
     99	.config_ctl_hi_val = 0x00002261,
    100	.config_ctl_hi1_val = 0x329A299C,
    101	.user_ctl_val = 0x00005100,
    102	.user_ctl_hi_val = 0x00000805,
    103	.user_ctl_hi1_val = 0x00000000,
    104};
    105
    106static struct clk_alpha_pll lpass_aon_cc_pll = {
    107	.offset = 0x0,
    108	.vco_table = lucid_vco,
    109	.num_vco = ARRAY_SIZE(lucid_vco),
    110	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
    111	.clkr = {
    112		.hw.init = &(const struct clk_init_data){
    113			.name = "lpass_aon_cc_pll",
    114			.parent_data = &(const struct clk_parent_data){
    115				.index = 0,
    116			},
    117			.num_parents = 1,
    118			.ops = &clk_alpha_pll_lucid_ops,
    119		},
    120	},
    121};
    122
    123static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_even[] = {
    124	{ 0x1, 2 },
    125	{ }
    126};
    127
    128static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_even = {
    129	.offset = 0x0,
    130	.post_div_shift = 8,
    131	.post_div_table = post_div_table_lpass_aon_cc_pll_out_even,
    132	.num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_even),
    133	.width = 4,
    134	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
    135	.clkr.hw.init = &(const struct clk_init_data){
    136		.name = "lpass_aon_cc_pll_out_even",
    137		.parent_hws = (const struct clk_hw*[]){
    138			&lpass_aon_cc_pll.clkr.hw,
    139		},
    140		.num_parents = 1,
    141		.ops = &clk_alpha_pll_postdiv_lucid_ops,
    142	},
    143};
    144
    145static const struct clk_div_table post_div_table_lpass_aon_cc_pll_out_odd[] = {
    146	{ 0x5, 5 },
    147	{ }
    148};
    149
    150static struct clk_alpha_pll_postdiv lpass_aon_cc_pll_out_odd = {
    151	.offset = 0x0,
    152	.post_div_shift = 12,
    153	.post_div_table = post_div_table_lpass_aon_cc_pll_out_odd,
    154	.num_post_div = ARRAY_SIZE(post_div_table_lpass_aon_cc_pll_out_odd),
    155	.width = 4,
    156	.regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_LUCID],
    157	.clkr.hw.init = &(const struct clk_init_data){
    158		.name = "lpass_aon_cc_pll_out_odd",
    159		.parent_hws = (const struct clk_hw*[]){
    160			&lpass_aon_cc_pll.clkr.hw,
    161		},
    162		.num_parents = 1,
    163		.ops = &clk_alpha_pll_postdiv_lucid_ops,
    164	},
    165};
    166
    167static const struct parent_map lpass_audio_cc_parent_map_0[] = {
    168	{ P_BI_TCXO, 0 },
    169	{ P_LPASS_AUDIO_CC_PLL_OUT_AUX, 3 },
    170	{ P_LPASS_AON_CC_PLL_OUT_ODD, 5 },
    171	{ P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 6 },
    172};
    173
    174static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src;
    175static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src;
    176
    177static const struct clk_parent_data lpass_audio_cc_parent_data_0[] = {
    178	{ .index = 0 },
    179	{ .hw = &lpass_audio_cc_pll.clkr.hw },
    180	{ .hw = &lpass_aon_cc_pll_out_odd.clkr.hw },
    181	{ .hw = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr.hw },
    182};
    183
    184static const struct parent_map lpass_aon_cc_parent_map_0[] = {
    185	{ P_BI_TCXO, 0 },
    186	{ P_LPASS_AON_CC_PLL_OUT_EVEN, 4 },
    187};
    188
    189static const struct clk_parent_data lpass_aon_cc_parent_data_0[] = {
    190	{ .index = 0 },
    191	{ .hw = &lpass_aon_cc_pll_out_even.clkr.hw },
    192};
    193
    194static const struct parent_map lpass_aon_cc_parent_map_1[] = {
    195	{ P_BI_TCXO, 0 },
    196	{ P_LPASS_AON_CC_PLL_OUT_ODD, 1 },
    197	{ P_LPASS_AUDIO_CC_PLL_MAIN_DIV_CLK, 6 },
    198};
    199
    200static const struct clk_parent_data lpass_aon_cc_parent_data_1[] = {
    201	{ .index = 0 },
    202	{ .hw = &lpass_aon_cc_pll_out_odd.clkr.hw },
    203	{ .hw = &lpass_audio_cc_pll_out_main_div_clk_src.clkr.hw },
    204};
    205
    206static const struct freq_tbl ftbl_lpass_aon_cc_main_rcg_clk_src[] = {
    207	F(38400000, P_LPASS_AON_CC_PLL_OUT_EVEN, 8, 0, 0),
    208	F(76800000, P_LPASS_AON_CC_PLL_OUT_EVEN, 4, 0, 0),
    209	F(153600000, P_LPASS_AON_CC_PLL_OUT_EVEN, 2, 0, 0),
    210	{ }
    211};
    212
    213static struct clk_rcg2 lpass_aon_cc_main_rcg_clk_src = {
    214	.cmd_rcgr = 0x1000,
    215	.mnd_width = 0,
    216	.hid_width = 5,
    217	.parent_map = lpass_aon_cc_parent_map_0,
    218	.freq_tbl = ftbl_lpass_aon_cc_main_rcg_clk_src,
    219	.clkr.hw.init = &(const struct clk_init_data){
    220		.name = "lpass_aon_cc_main_rcg_clk_src",
    221		.parent_data = lpass_aon_cc_parent_data_0,
    222		.num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_0),
    223		.flags = CLK_OPS_PARENT_ENABLE,
    224		.ops = &clk_rcg2_ops,
    225	},
    226};
    227
    228static const struct freq_tbl ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src[] = {
    229	F(19200000, P_BI_TCXO, 1, 0, 0),
    230	F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0),
    231	{ }
    232};
    233
    234static struct clk_rcg2 lpass_aon_cc_tx_mclk_rcg_clk_src = {
    235	.cmd_rcgr = 0x13004,
    236	.mnd_width = 0,
    237	.hid_width = 5,
    238	.parent_map = lpass_aon_cc_parent_map_1,
    239	.freq_tbl = ftbl_lpass_aon_cc_tx_mclk_rcg_clk_src,
    240	.clkr.hw.init = &(const struct clk_init_data){
    241		.name = "lpass_aon_cc_tx_mclk_rcg_clk_src",
    242		.parent_data = lpass_aon_cc_parent_data_1,
    243		.num_parents = ARRAY_SIZE(lpass_aon_cc_parent_data_1),
    244		.ops = &clk_rcg2_ops,
    245	},
    246};
    247
    248static struct clk_regmap_div lpass_audio_cc_pll_out_aux2_div_clk_src = {
    249	.reg = 0x48,
    250	.shift = 0,
    251	.width = 4,
    252	.clkr.hw.init = &(const struct clk_init_data) {
    253		.name = "lpass_audio_cc_pll_out_aux2_div_clk_src",
    254		.parent_hws = (const struct clk_hw*[]){
    255			&lpass_audio_cc_pll_out_aux2.clkr.hw,
    256		},
    257		.num_parents = 1,
    258		.flags = CLK_SET_RATE_PARENT,
    259		.ops = &clk_regmap_div_ro_ops,
    260	},
    261};
    262
    263static struct clk_regmap_div lpass_audio_cc_pll_out_main_div_clk_src = {
    264	.reg = 0x3c,
    265	.shift = 0,
    266	.width = 4,
    267	.clkr.hw.init = &(const struct clk_init_data) {
    268		.name = "lpass_audio_cc_pll_out_main_div_clk_src",
    269		.parent_hws = (const struct clk_hw*[]){
    270			&lpass_audio_cc_pll.clkr.hw,
    271		},
    272		.num_parents = 1,
    273		.flags = CLK_SET_RATE_PARENT,
    274		.ops = &clk_regmap_div_ro_ops,
    275	},
    276};
    277
    278static struct clk_regmap_div lpass_aon_cc_cdiv_tx_mclk_div_clk_src = {
    279	.reg = 0x13010,
    280	.shift = 0,
    281	.width = 4,
    282	.clkr.hw.init = &(const struct clk_init_data) {
    283		.name = "lpass_aon_cc_cdiv_tx_mclk_div_clk_src",
    284		.parent_hws = (const struct clk_hw*[]){
    285			&lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw,
    286		},
    287		.num_parents = 1,
    288		.flags = CLK_SET_RATE_PARENT,
    289		.ops = &clk_regmap_div_ro_ops,
    290	},
    291};
    292
    293static struct clk_regmap_div lpass_aon_cc_pll_out_main_cdiv_div_clk_src = {
    294	.reg = 0x80,
    295	.shift = 0,
    296	.width = 4,
    297	.clkr.hw.init = &(const struct clk_init_data) {
    298		.name = "lpass_aon_cc_pll_out_main_cdiv_div_clk_src",
    299		.parent_hws = (const struct clk_hw*[]){
    300			&lpass_aon_cc_pll.clkr.hw,
    301		},
    302		.num_parents = 1,
    303		.flags = CLK_SET_RATE_PARENT,
    304		.ops = &clk_regmap_div_ro_ops,
    305	},
    306};
    307
    308static const struct freq_tbl ftbl_lpass_audio_cc_ext_mclk0_clk_src[] = {
    309	F(256000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 32),
    310	F(352800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 32),
    311	F(512000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 16),
    312	F(705600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 16),
    313	F(768000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 16),
    314	F(1024000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 8),
    315	F(1411200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 8),
    316	F(1536000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 8),
    317	F(2048000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 4),
    318	F(2822400, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 4),
    319	F(3072000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 4),
    320	F(4096000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 1, 2),
    321	F(5644800, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 1, 2),
    322	F(6144000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 1, 2),
    323	F(8192000, P_LPASS_AON_CC_PLL_OUT_ODD, 15, 0, 0),
    324	F(9600000, P_BI_TCXO, 2, 0, 0),
    325	F(11289600, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 10, 0, 0),
    326	F(12288000, P_LPASS_AON_CC_PLL_OUT_ODD, 10, 0, 0),
    327	F(19200000, P_BI_TCXO, 1, 0, 0),
    328	F(22579200, P_LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC, 5, 0, 0),
    329	F(24576000, P_LPASS_AON_CC_PLL_OUT_ODD, 5, 0, 0),
    330	{ }
    331};
    332
    333static struct clk_rcg2 lpass_audio_cc_ext_mclk0_clk_src = {
    334	.cmd_rcgr = 0x20004,
    335	.mnd_width = 8,
    336	.hid_width = 5,
    337	.parent_map = lpass_audio_cc_parent_map_0,
    338	.freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
    339	.clkr.hw.init = &(const struct clk_init_data){
    340		.name = "lpass_audio_cc_ext_mclk0_clk_src",
    341		.parent_data = lpass_audio_cc_parent_data_0,
    342		.num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
    343		.ops = &clk_rcg2_ops,
    344	},
    345};
    346
    347static struct clk_rcg2 lpass_audio_cc_ext_mclk1_clk_src = {
    348	.cmd_rcgr = 0x21004,
    349	.mnd_width = 8,
    350	.hid_width = 5,
    351	.parent_map = lpass_audio_cc_parent_map_0,
    352	.freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
    353	.clkr.hw.init = &(const struct clk_init_data){
    354		.name = "lpass_audio_cc_ext_mclk1_clk_src",
    355		.parent_data = lpass_audio_cc_parent_data_0,
    356		.num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
    357		.ops = &clk_rcg2_ops,
    358	},
    359};
    360
    361static struct clk_rcg2 lpass_audio_cc_rx_mclk_clk_src = {
    362	.cmd_rcgr = 0x24004,
    363	.mnd_width = 8,
    364	.hid_width = 5,
    365	.parent_map = lpass_audio_cc_parent_map_0,
    366	.freq_tbl = ftbl_lpass_audio_cc_ext_mclk0_clk_src,
    367	.clkr.hw.init = &(const struct clk_init_data){
    368		.name = "lpass_audio_cc_rx_mclk_clk_src",
    369		.parent_data = lpass_audio_cc_parent_data_0,
    370		.num_parents = ARRAY_SIZE(lpass_audio_cc_parent_data_0),
    371		.ops = &clk_rcg2_ops,
    372	},
    373};
    374
    375static struct clk_regmap_div lpass_audio_cc_cdiv_rx_mclk_div_clk_src = {
    376	.reg = 0x240d0,
    377	.shift = 0,
    378	.width = 4,
    379	.clkr.hw.init = &(const struct clk_init_data) {
    380		.name = "lpass_audio_cc_cdiv_rx_mclk_div_clk_src",
    381		.parent_hws = (const struct clk_hw*[]){
    382			&lpass_audio_cc_rx_mclk_clk_src.clkr.hw,
    383		},
    384		.num_parents = 1,
    385		.flags = CLK_SET_RATE_PARENT,
    386		.ops = &clk_regmap_div_ro_ops,
    387	},
    388};
    389
    390static struct clk_branch lpass_aon_cc_audio_hm_h_clk;
    391
    392static struct clk_branch lpass_audio_cc_codec_mem0_clk = {
    393	.halt_reg = 0x1e004,
    394	.halt_check = BRANCH_HALT,
    395	.clkr = {
    396		.enable_reg = 0x1e004,
    397		.enable_mask = BIT(0),
    398		.hw.init = &(const struct clk_init_data){
    399			.name = "lpass_audio_cc_codec_mem0_clk",
    400			.parent_hws = (const struct clk_hw*[]){
    401				&lpass_aon_cc_audio_hm_h_clk.clkr.hw,
    402			},
    403			.num_parents = 1,
    404			.flags = CLK_SET_RATE_PARENT,
    405			.ops = &clk_branch2_ops,
    406		},
    407	},
    408};
    409
    410static struct clk_branch lpass_audio_cc_codec_mem1_clk = {
    411	.halt_reg = 0x1e008,
    412	.halt_check = BRANCH_HALT,
    413	.clkr = {
    414		.enable_reg = 0x1e008,
    415		.enable_mask = BIT(0),
    416		.hw.init = &(const struct clk_init_data){
    417			.name = "lpass_audio_cc_codec_mem1_clk",
    418			.parent_hws = (const struct clk_hw*[]){
    419				&lpass_aon_cc_audio_hm_h_clk.clkr.hw,
    420			},
    421			.num_parents = 1,
    422			.flags = CLK_SET_RATE_PARENT,
    423			.ops = &clk_branch2_ops,
    424		},
    425	},
    426};
    427
    428static struct clk_branch lpass_audio_cc_codec_mem2_clk = {
    429	.halt_reg = 0x1e00c,
    430	.halt_check = BRANCH_HALT,
    431	.clkr = {
    432		.enable_reg = 0x1e00c,
    433		.enable_mask = BIT(0),
    434		.hw.init = &(const struct clk_init_data){
    435			.name = "lpass_audio_cc_codec_mem2_clk",
    436			.parent_hws = (const struct clk_hw*[]){
    437				&lpass_aon_cc_audio_hm_h_clk.clkr.hw,
    438			},
    439			.num_parents = 1,
    440			.flags = CLK_SET_RATE_PARENT,
    441			.ops = &clk_branch2_ops,
    442		},
    443	},
    444};
    445
    446static struct clk_branch lpass_audio_cc_codec_mem_clk = {
    447	.halt_reg = 0x1e000,
    448	.halt_check = BRANCH_HALT,
    449	.clkr = {
    450		.enable_reg = 0x1e000,
    451		.enable_mask = BIT(0),
    452		.hw.init = &(const struct clk_init_data){
    453			.name = "lpass_audio_cc_codec_mem_clk",
    454			.parent_hws = (const struct clk_hw*[]){
    455				&lpass_aon_cc_audio_hm_h_clk.clkr.hw,
    456			},
    457			.num_parents = 1,
    458			.flags = CLK_SET_RATE_PARENT,
    459			.ops = &clk_branch2_ops,
    460		},
    461	},
    462};
    463
    464static struct clk_branch lpass_audio_cc_ext_mclk0_clk = {
    465	.halt_reg = 0x20018,
    466	.halt_check = BRANCH_HALT,
    467	.clkr = {
    468		.enable_reg = 0x20018,
    469		.enable_mask = BIT(0),
    470		.hw.init = &(const struct clk_init_data){
    471			.name = "lpass_audio_cc_ext_mclk0_clk",
    472			.parent_hws = (const struct clk_hw*[]){
    473				&lpass_audio_cc_ext_mclk0_clk_src.clkr.hw,
    474			},
    475			.num_parents = 1,
    476			.flags = CLK_SET_RATE_PARENT,
    477			.ops = &clk_branch2_ops,
    478		},
    479	},
    480};
    481
    482static struct clk_branch lpass_audio_cc_ext_mclk1_clk = {
    483	.halt_reg = 0x21018,
    484	.halt_check = BRANCH_HALT,
    485	.clkr = {
    486		.enable_reg = 0x21018,
    487		.enable_mask = BIT(0),
    488		.hw.init = &(const struct clk_init_data){
    489			.name = "lpass_audio_cc_ext_mclk1_clk",
    490			.parent_hws = (const struct clk_hw*[]){
    491				&lpass_audio_cc_ext_mclk1_clk_src.clkr.hw,
    492			},
    493			.num_parents = 1,
    494			.flags = CLK_SET_RATE_PARENT,
    495			.ops = &clk_branch2_ops,
    496		},
    497	},
    498};
    499
    500static struct clk_branch lpass_audio_cc_rx_mclk_2x_clk = {
    501	.halt_reg = 0x240cc,
    502	.halt_check = BRANCH_HALT,
    503	.clkr = {
    504		.enable_reg = 0x240cc,
    505		.enable_mask = BIT(0),
    506		.hw.init = &(const struct clk_init_data){
    507			.name = "lpass_audio_cc_rx_mclk_2x_clk",
    508			.parent_hws = (const struct clk_hw*[]){
    509				&lpass_audio_cc_rx_mclk_clk_src.clkr.hw,
    510			},
    511			.num_parents = 1,
    512			.flags = CLK_SET_RATE_PARENT,
    513			.ops = &clk_branch2_ops,
    514		},
    515	},
    516};
    517
    518static struct clk_branch lpass_audio_cc_rx_mclk_clk = {
    519	.halt_reg = 0x240d4,
    520	.halt_check = BRANCH_HALT,
    521	.clkr = {
    522		.enable_reg = 0x240d4,
    523		.enable_mask = BIT(0),
    524		.hw.init = &(const struct clk_init_data){
    525			.name = "lpass_audio_cc_rx_mclk_clk",
    526			.parent_hws = (const struct clk_hw*[]){
    527				&lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr.hw,
    528			},
    529			.num_parents = 1,
    530			.flags = CLK_SET_RATE_PARENT,
    531			.ops = &clk_branch2_ops,
    532		},
    533	},
    534};
    535
    536static struct clk_branch lpass_aon_cc_audio_hm_h_clk = {
    537	.halt_reg = 0x9014,
    538	.halt_check = BRANCH_HALT,
    539	.clkr = {
    540		.enable_reg = 0x9014,
    541		.enable_mask = BIT(0),
    542		.hw.init = &(const struct clk_init_data){
    543			.name = "lpass_aon_cc_audio_hm_h_clk",
    544			.parent_hws = (const struct clk_hw*[]){
    545				&lpass_aon_cc_main_rcg_clk_src.clkr.hw,
    546			},
    547			.num_parents = 1,
    548			.flags = CLK_SET_RATE_PARENT,
    549			.ops = &clk_branch2_aon_ops,
    550		},
    551	},
    552};
    553
    554static struct clk_branch lpass_aon_cc_va_mem0_clk = {
    555	.halt_reg = 0x9028,
    556	.halt_check = BRANCH_HALT,
    557	.clkr = {
    558		.enable_reg = 0x9028,
    559		.enable_mask = BIT(0),
    560		.hw.init = &(const struct clk_init_data){
    561			.name = "lpass_aon_cc_va_mem0_clk",
    562			.parent_hws = (const struct clk_hw*[]){
    563				&lpass_aon_cc_main_rcg_clk_src.clkr.hw,
    564			},
    565			.num_parents = 1,
    566			.flags = CLK_SET_RATE_PARENT,
    567			.ops = &clk_branch2_ops,
    568		},
    569	},
    570};
    571
    572static struct clk_branch lpass_aon_cc_tx_mclk_2x_clk = {
    573	.halt_reg = 0x1300c,
    574	.halt_check = BRANCH_HALT,
    575	.clkr = {
    576		.enable_reg = 0x1300c,
    577		.enable_mask = BIT(0),
    578		.hw.init = &(const struct clk_init_data){
    579			.name = "lpass_aon_cc_tx_mclk_2x_clk",
    580			.parent_hws = (const struct clk_hw*[]){
    581				&lpass_aon_cc_tx_mclk_rcg_clk_src.clkr.hw,
    582			},
    583			.num_parents = 1,
    584			.flags = CLK_SET_RATE_PARENT,
    585			.ops = &clk_branch2_ops,
    586		},
    587	},
    588};
    589
    590static struct clk_branch lpass_aon_cc_tx_mclk_clk = {
    591	.halt_reg = 0x13014,
    592	.halt_check = BRANCH_HALT,
    593	.clkr = {
    594		.enable_reg = 0x13014,
    595		.enable_mask = BIT(0),
    596		.hw.init = &(const struct clk_init_data){
    597			.name = "lpass_aon_cc_tx_mclk_clk",
    598			.parent_hws = (const struct clk_hw*[]){
    599				&lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr.hw,
    600			},
    601			.num_parents = 1,
    602			.flags = CLK_SET_RATE_PARENT,
    603			.ops = &clk_branch2_ops,
    604		},
    605	},
    606};
    607
    608static struct gdsc lpass_aon_cc_lpass_audio_hm_gdsc = {
    609	.gdscr = 0x9090,
    610	.pd = {
    611		.name = "lpass_aon_cc_lpass_audio_hm_gdsc",
    612	},
    613	.pwrsts = PWRSTS_OFF_ON,
    614	.flags = RETAIN_FF_ENABLE,
    615};
    616
    617static struct clk_regmap *lpass_aon_cc_sc7280_clocks[] = {
    618	[LPASS_AON_CC_AUDIO_HM_H_CLK] = &lpass_aon_cc_audio_hm_h_clk.clkr,
    619	[LPASS_AON_CC_VA_MEM0_CLK] = &lpass_aon_cc_va_mem0_clk.clkr,
    620	[LPASS_AON_CC_CDIV_TX_MCLK_DIV_CLK_SRC] = &lpass_aon_cc_cdiv_tx_mclk_div_clk_src.clkr,
    621	[LPASS_AON_CC_MAIN_RCG_CLK_SRC] = &lpass_aon_cc_main_rcg_clk_src.clkr,
    622	[LPASS_AON_CC_PLL] = &lpass_aon_cc_pll.clkr,
    623	[LPASS_AON_CC_PLL_OUT_EVEN] = &lpass_aon_cc_pll_out_even.clkr,
    624	[LPASS_AON_CC_PLL_OUT_MAIN_CDIV_DIV_CLK_SRC] =
    625		&lpass_aon_cc_pll_out_main_cdiv_div_clk_src.clkr,
    626	[LPASS_AON_CC_PLL_OUT_ODD] = &lpass_aon_cc_pll_out_odd.clkr,
    627	[LPASS_AON_CC_TX_MCLK_2X_CLK] = &lpass_aon_cc_tx_mclk_2x_clk.clkr,
    628	[LPASS_AON_CC_TX_MCLK_CLK] = &lpass_aon_cc_tx_mclk_clk.clkr,
    629	[LPASS_AON_CC_TX_MCLK_RCG_CLK_SRC] = &lpass_aon_cc_tx_mclk_rcg_clk_src.clkr,
    630};
    631
    632static struct gdsc *lpass_aon_cc_sc7280_gdscs[] = {
    633	[LPASS_AON_CC_LPASS_AUDIO_HM_GDSC] = &lpass_aon_cc_lpass_audio_hm_gdsc,
    634};
    635
    636static struct clk_regmap *lpass_audio_cc_sc7280_clocks[] = {
    637	[LPASS_AUDIO_CC_CDIV_RX_MCLK_DIV_CLK_SRC] = &lpass_audio_cc_cdiv_rx_mclk_div_clk_src.clkr,
    638	[LPASS_AUDIO_CC_CODEC_MEM0_CLK] = &lpass_audio_cc_codec_mem0_clk.clkr,
    639	[LPASS_AUDIO_CC_CODEC_MEM1_CLK] = &lpass_audio_cc_codec_mem1_clk.clkr,
    640	[LPASS_AUDIO_CC_CODEC_MEM2_CLK] = &lpass_audio_cc_codec_mem2_clk.clkr,
    641	[LPASS_AUDIO_CC_CODEC_MEM_CLK] = &lpass_audio_cc_codec_mem_clk.clkr,
    642	[LPASS_AUDIO_CC_EXT_MCLK0_CLK] = &lpass_audio_cc_ext_mclk0_clk.clkr,
    643	[LPASS_AUDIO_CC_EXT_MCLK0_CLK_SRC] = &lpass_audio_cc_ext_mclk0_clk_src.clkr,
    644	[LPASS_AUDIO_CC_EXT_MCLK1_CLK] = &lpass_audio_cc_ext_mclk1_clk.clkr,
    645	[LPASS_AUDIO_CC_EXT_MCLK1_CLK_SRC] = &lpass_audio_cc_ext_mclk1_clk_src.clkr,
    646	[LPASS_AUDIO_CC_PLL] = &lpass_audio_cc_pll.clkr,
    647	[LPASS_AUDIO_CC_PLL_OUT_AUX2] = &lpass_audio_cc_pll_out_aux2.clkr,
    648	[LPASS_AUDIO_CC_PLL_OUT_AUX2_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_aux2_div_clk_src.clkr,
    649	[LPASS_AUDIO_CC_PLL_OUT_MAIN_DIV_CLK_SRC] = &lpass_audio_cc_pll_out_main_div_clk_src.clkr,
    650	[LPASS_AUDIO_CC_RX_MCLK_2X_CLK] = &lpass_audio_cc_rx_mclk_2x_clk.clkr,
    651	[LPASS_AUDIO_CC_RX_MCLK_CLK] = &lpass_audio_cc_rx_mclk_clk.clkr,
    652	[LPASS_AUDIO_CC_RX_MCLK_CLK_SRC] = &lpass_audio_cc_rx_mclk_clk_src.clkr,
    653};
    654
    655static struct regmap_config lpass_audio_cc_sc7280_regmap_config = {
    656	.reg_bits = 32,
    657	.reg_stride = 4,
    658	.val_bits = 32,
    659	.fast_io = true,
    660};
    661
    662static const struct qcom_cc_desc lpass_audio_cc_sc7280_desc = {
    663	.config = &lpass_audio_cc_sc7280_regmap_config,
    664	.clks = lpass_audio_cc_sc7280_clocks,
    665	.num_clks = ARRAY_SIZE(lpass_audio_cc_sc7280_clocks),
    666};
    667
    668static const struct of_device_id lpass_audio_cc_sc7280_match_table[] = {
    669	{ .compatible = "qcom,sc7280-lpassaudiocc" },
    670	{ }
    671};
    672MODULE_DEVICE_TABLE(of, lpass_audio_cc_sc7280_match_table);
    673
    674static void lpassaudio_pm_runtime_disable(void *data)
    675{
    676	pm_runtime_disable(data);
    677}
    678
    679static void lpassaudio_pm_clk_destroy(void *data)
    680{
    681	pm_clk_destroy(data);
    682}
    683
    684static int lpassaudio_create_pm_clks(struct platform_device *pdev)
    685{
    686	int ret;
    687
    688	pm_runtime_use_autosuspend(&pdev->dev);
    689	pm_runtime_set_autosuspend_delay(&pdev->dev, 50);
    690	pm_runtime_enable(&pdev->dev);
    691
    692	ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_runtime_disable, &pdev->dev);
    693	if (ret)
    694		return ret;
    695
    696	ret = pm_clk_create(&pdev->dev);
    697	if (ret)
    698		return ret;
    699
    700	ret = devm_add_action_or_reset(&pdev->dev, lpassaudio_pm_clk_destroy, &pdev->dev);
    701	if (ret)
    702		return ret;
    703
    704	ret = pm_clk_add(&pdev->dev, "iface");
    705	if (ret < 0)
    706		dev_err(&pdev->dev, "failed to acquire iface clock\n");
    707
    708	return ret;
    709}
    710
    711static int lpass_audio_cc_sc7280_probe(struct platform_device *pdev)
    712{
    713	const struct qcom_cc_desc *desc;
    714	struct regmap *regmap;
    715	int ret;
    716
    717	ret = lpassaudio_create_pm_clks(pdev);
    718	if (ret)
    719		return ret;
    720
    721	lpass_audio_cc_sc7280_regmap_config.name = "lpassaudio_cc";
    722	lpass_audio_cc_sc7280_regmap_config.max_register = 0x2f000;
    723	desc = &lpass_audio_cc_sc7280_desc;
    724
    725	regmap = qcom_cc_map(pdev, desc);
    726	if (IS_ERR(regmap)) {
    727		pm_runtime_disable(&pdev->dev);
    728		return PTR_ERR(regmap);
    729	}
    730
    731	clk_zonda_pll_configure(&lpass_audio_cc_pll, regmap, &lpass_audio_cc_pll_config);
    732
    733	/* PLL settings */
    734	regmap_write(regmap, 0x4, 0x3b);
    735	regmap_write(regmap, 0x8, 0xff05);
    736
    737	ret = qcom_cc_really_probe(pdev, &lpass_audio_cc_sc7280_desc, regmap);
    738	if (ret) {
    739		dev_err(&pdev->dev, "Failed to register LPASS AUDIO CC clocks\n");
    740		pm_runtime_disable(&pdev->dev);
    741		return ret;
    742	}
    743
    744	pm_runtime_mark_last_busy(&pdev->dev);
    745	pm_runtime_put_autosuspend(&pdev->dev);
    746	pm_runtime_put_sync(&pdev->dev);
    747
    748	return ret;
    749}
    750
    751static const struct dev_pm_ops lpass_audio_cc_pm_ops = {
    752	SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
    753};
    754
    755static struct platform_driver lpass_audio_cc_sc7280_driver = {
    756	.probe = lpass_audio_cc_sc7280_probe,
    757	.driver = {
    758		.name = "lpass_audio_cc-sc7280",
    759		.of_match_table = lpass_audio_cc_sc7280_match_table,
    760		.pm = &lpass_audio_cc_pm_ops,
    761	},
    762};
    763
    764static const struct qcom_cc_desc lpass_aon_cc_sc7280_desc = {
    765	.config = &lpass_audio_cc_sc7280_regmap_config,
    766	.clks = lpass_aon_cc_sc7280_clocks,
    767	.num_clks = ARRAY_SIZE(lpass_aon_cc_sc7280_clocks),
    768	.gdscs = lpass_aon_cc_sc7280_gdscs,
    769	.num_gdscs = ARRAY_SIZE(lpass_aon_cc_sc7280_gdscs),
    770};
    771
    772static const struct of_device_id lpass_aon_cc_sc7280_match_table[] = {
    773	{ .compatible = "qcom,sc7280-lpassaoncc" },
    774	{ }
    775};
    776MODULE_DEVICE_TABLE(of, lpass_aon_cc_sc7280_match_table);
    777
    778static int lpass_aon_cc_sc7280_probe(struct platform_device *pdev)
    779{
    780	const struct qcom_cc_desc *desc;
    781	struct regmap *regmap;
    782	int ret;
    783
    784	ret = lpassaudio_create_pm_clks(pdev);
    785	if (ret)
    786		return ret;
    787
    788	lpass_audio_cc_sc7280_regmap_config.name = "lpasscc_aon";
    789	lpass_audio_cc_sc7280_regmap_config.max_register = 0xa0008;
    790	desc = &lpass_aon_cc_sc7280_desc;
    791
    792	regmap = qcom_cc_map(pdev, desc);
    793	if (IS_ERR(regmap))
    794		return PTR_ERR(regmap);
    795
    796	clk_lucid_pll_configure(&lpass_aon_cc_pll, regmap, &lpass_aon_cc_pll_config);
    797
    798	ret = qcom_cc_really_probe(pdev, &lpass_aon_cc_sc7280_desc, regmap);
    799	if (ret)
    800		dev_err(&pdev->dev, "Failed to register LPASS AON CC clocks\n");
    801
    802	pm_runtime_mark_last_busy(&pdev->dev);
    803	pm_runtime_put_autosuspend(&pdev->dev);
    804	pm_runtime_put_sync(&pdev->dev);
    805
    806	return ret;
    807}
    808
    809static struct platform_driver lpass_aon_cc_sc7280_driver = {
    810	.probe = lpass_aon_cc_sc7280_probe,
    811	.driver = {
    812		.name = "lpass_aon_cc-sc7280",
    813		.of_match_table = lpass_aon_cc_sc7280_match_table,
    814		.pm = &lpass_audio_cc_pm_ops,
    815	},
    816};
    817
    818static int __init lpass_audio_cc_sc7280_init(void)
    819{
    820	int ret;
    821
    822	ret = platform_driver_register(&lpass_aon_cc_sc7280_driver);
    823	if (ret)
    824		return ret;
    825
    826	return platform_driver_register(&lpass_audio_cc_sc7280_driver);
    827}
    828subsys_initcall(lpass_audio_cc_sc7280_init);
    829
    830static void __exit lpass_audio_cc_sc7280_exit(void)
    831{
    832	platform_driver_unregister(&lpass_audio_cc_sc7280_driver);
    833	platform_driver_unregister(&lpass_aon_cc_sc7280_driver);
    834}
    835module_exit(lpass_audio_cc_sc7280_exit);
    836
    837MODULE_DESCRIPTION("QTI LPASS_AUDIO_CC SC7280 Driver");
    838MODULE_LICENSE("GPL v2");