18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2020, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 78c2ecf20Sopenharmony_ci#include <linux/err.h> 88c2ecf20Sopenharmony_ci#include <linux/module.h> 98c2ecf20Sopenharmony_ci#include <linux/of_device.h> 108c2ecf20Sopenharmony_ci#include <linux/pm_clock.h> 118c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 128c2ecf20Sopenharmony_ci#include <linux/of.h> 138c2ecf20Sopenharmony_ci#include <linux/regmap.h> 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <dt-bindings/clock/qcom,lpasscorecc-sc7180.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include "clk-alpha-pll.h" 188c2ecf20Sopenharmony_ci#include "clk-branch.h" 198c2ecf20Sopenharmony_ci#include "clk-rcg.h" 208c2ecf20Sopenharmony_ci#include "clk-regmap.h" 218c2ecf20Sopenharmony_ci#include "common.h" 228c2ecf20Sopenharmony_ci#include "gdsc.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_cienum { 258c2ecf20Sopenharmony_ci P_BI_TCXO, 268c2ecf20Sopenharmony_ci P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 278c2ecf20Sopenharmony_ci P_SLEEP_CLK, 288c2ecf20Sopenharmony_ci}; 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic struct pll_vco fabia_vco[] = { 318c2ecf20Sopenharmony_ci { 249600000, 2000000000, 0 }, 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_cistatic const struct alpha_pll_config lpass_lpaaudio_dig_pll_config = { 358c2ecf20Sopenharmony_ci .l = 0x20, 368c2ecf20Sopenharmony_ci .alpha = 0x0, 378c2ecf20Sopenharmony_ci .config_ctl_val = 0x20485699, 388c2ecf20Sopenharmony_ci .config_ctl_hi_val = 0x00002067, 398c2ecf20Sopenharmony_ci .test_ctl_val = 0x40000000, 408c2ecf20Sopenharmony_ci .test_ctl_hi_val = 0x00000000, 418c2ecf20Sopenharmony_ci .user_ctl_val = 0x00005105, 428c2ecf20Sopenharmony_ci .user_ctl_hi_val = 0x00004805, 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistatic const u8 clk_alpha_pll_regs_offset[][PLL_OFF_MAX_REGS] = { 468c2ecf20Sopenharmony_ci [CLK_ALPHA_PLL_TYPE_FABIA] = { 478c2ecf20Sopenharmony_ci [PLL_OFF_L_VAL] = 0x04, 488c2ecf20Sopenharmony_ci [PLL_OFF_CAL_L_VAL] = 0x8, 498c2ecf20Sopenharmony_ci [PLL_OFF_USER_CTL] = 0x0c, 508c2ecf20Sopenharmony_ci [PLL_OFF_USER_CTL_U] = 0x10, 518c2ecf20Sopenharmony_ci [PLL_OFF_USER_CTL_U1] = 0x14, 528c2ecf20Sopenharmony_ci [PLL_OFF_CONFIG_CTL] = 0x18, 538c2ecf20Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U] = 0x1C, 548c2ecf20Sopenharmony_ci [PLL_OFF_CONFIG_CTL_U1] = 0x20, 558c2ecf20Sopenharmony_ci [PLL_OFF_TEST_CTL] = 0x24, 568c2ecf20Sopenharmony_ci [PLL_OFF_TEST_CTL_U] = 0x28, 578c2ecf20Sopenharmony_ci [PLL_OFF_STATUS] = 0x30, 588c2ecf20Sopenharmony_ci [PLL_OFF_OPMODE] = 0x38, 598c2ecf20Sopenharmony_ci [PLL_OFF_FRAC] = 0x40, 608c2ecf20Sopenharmony_ci }, 618c2ecf20Sopenharmony_ci}; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic struct clk_alpha_pll lpass_lpaaudio_dig_pll = { 648c2ecf20Sopenharmony_ci .offset = 0x1000, 658c2ecf20Sopenharmony_ci .vco_table = fabia_vco, 668c2ecf20Sopenharmony_ci .num_vco = ARRAY_SIZE(fabia_vco), 678c2ecf20Sopenharmony_ci .regs = clk_alpha_pll_regs_offset[CLK_ALPHA_PLL_TYPE_FABIA], 688c2ecf20Sopenharmony_ci .clkr = { 698c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 708c2ecf20Sopenharmony_ci .name = "lpass_lpaaudio_dig_pll", 718c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 728c2ecf20Sopenharmony_ci .fw_name = "bi_tcxo", 738c2ecf20Sopenharmony_ci }, 748c2ecf20Sopenharmony_ci .num_parents = 1, 758c2ecf20Sopenharmony_ci .ops = &clk_alpha_pll_fabia_ops, 768c2ecf20Sopenharmony_ci }, 778c2ecf20Sopenharmony_ci }, 788c2ecf20Sopenharmony_ci}; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_cistatic const struct clk_div_table 818c2ecf20Sopenharmony_ci post_div_table_lpass_lpaaudio_dig_pll_out_odd[] = { 828c2ecf20Sopenharmony_ci { 0x5, 5 }, 838c2ecf20Sopenharmony_ci { } 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistatic struct clk_alpha_pll_postdiv lpass_lpaaudio_dig_pll_out_odd = { 878c2ecf20Sopenharmony_ci .offset = 0x1000, 888c2ecf20Sopenharmony_ci .post_div_shift = 12, 898c2ecf20Sopenharmony_ci .post_div_table = post_div_table_lpass_lpaaudio_dig_pll_out_odd, 908c2ecf20Sopenharmony_ci .num_post_div = 918c2ecf20Sopenharmony_ci ARRAY_SIZE(post_div_table_lpass_lpaaudio_dig_pll_out_odd), 928c2ecf20Sopenharmony_ci .width = 4, 938c2ecf20Sopenharmony_ci .regs = clk_alpha_pll_regs[CLK_ALPHA_PLL_TYPE_FABIA], 948c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 958c2ecf20Sopenharmony_ci .name = "lpass_lpaaudio_dig_pll_out_odd", 968c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 978c2ecf20Sopenharmony_ci .hw = &lpass_lpaaudio_dig_pll.clkr.hw, 988c2ecf20Sopenharmony_ci }, 998c2ecf20Sopenharmony_ci .num_parents = 1, 1008c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1018c2ecf20Sopenharmony_ci .ops = &clk_alpha_pll_postdiv_fabia_ops, 1028c2ecf20Sopenharmony_ci }, 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic const struct parent_map lpass_core_cc_parent_map_0[] = { 1068c2ecf20Sopenharmony_ci { P_BI_TCXO, 0 }, 1078c2ecf20Sopenharmony_ci { P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5 }, 1088c2ecf20Sopenharmony_ci}; 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_cistatic const struct clk_parent_data lpass_core_cc_parent_data_0[] = { 1118c2ecf20Sopenharmony_ci { .fw_name = "bi_tcxo" }, 1128c2ecf20Sopenharmony_ci { .hw = &lpass_lpaaudio_dig_pll_out_odd.clkr.hw }, 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic const struct parent_map lpass_core_cc_parent_map_2[] = { 1168c2ecf20Sopenharmony_ci { P_BI_TCXO, 0 }, 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_cistatic struct clk_rcg2 core_clk_src = { 1208c2ecf20Sopenharmony_ci .cmd_rcgr = 0x1d000, 1218c2ecf20Sopenharmony_ci .mnd_width = 8, 1228c2ecf20Sopenharmony_ci .hid_width = 5, 1238c2ecf20Sopenharmony_ci .parent_map = lpass_core_cc_parent_map_2, 1248c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 1258c2ecf20Sopenharmony_ci .name = "core_clk_src", 1268c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 1278c2ecf20Sopenharmony_ci .fw_name = "bi_tcxo", 1288c2ecf20Sopenharmony_ci }, 1298c2ecf20Sopenharmony_ci .num_parents = 1, 1308c2ecf20Sopenharmony_ci .ops = &clk_rcg2_ops, 1318c2ecf20Sopenharmony_ci }, 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic const struct freq_tbl ftbl_ext_mclk0_clk_src[] = { 1358c2ecf20Sopenharmony_ci F(9600000, P_BI_TCXO, 2, 0, 0), 1368c2ecf20Sopenharmony_ci F(19200000, P_BI_TCXO, 1, 0, 0), 1378c2ecf20Sopenharmony_ci { } 1388c2ecf20Sopenharmony_ci}; 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic const struct freq_tbl ftbl_ext_lpaif_clk_src[] = { 1418c2ecf20Sopenharmony_ci F(256000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 32), 1428c2ecf20Sopenharmony_ci F(512000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 16), 1438c2ecf20Sopenharmony_ci F(768000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 16), 1448c2ecf20Sopenharmony_ci F(1024000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 8), 1458c2ecf20Sopenharmony_ci F(1536000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 8), 1468c2ecf20Sopenharmony_ci F(2048000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 4), 1478c2ecf20Sopenharmony_ci F(3072000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 4), 1488c2ecf20Sopenharmony_ci F(4096000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 1, 2), 1498c2ecf20Sopenharmony_ci F(6144000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 1, 2), 1508c2ecf20Sopenharmony_ci F(8192000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 15, 0, 0), 1518c2ecf20Sopenharmony_ci F(9600000, P_BI_TCXO, 2, 0, 0), 1528c2ecf20Sopenharmony_ci F(12288000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 10, 0, 0), 1538c2ecf20Sopenharmony_ci F(19200000, P_BI_TCXO, 1, 0, 0), 1548c2ecf20Sopenharmony_ci F(24576000, P_LPASS_LPAAUDIO_DIG_PLL_OUT_ODD, 5, 0, 0), 1558c2ecf20Sopenharmony_ci { } 1568c2ecf20Sopenharmony_ci}; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_cistatic struct clk_rcg2 ext_mclk0_clk_src = { 1598c2ecf20Sopenharmony_ci .cmd_rcgr = 0x20000, 1608c2ecf20Sopenharmony_ci .mnd_width = 8, 1618c2ecf20Sopenharmony_ci .hid_width = 5, 1628c2ecf20Sopenharmony_ci .parent_map = lpass_core_cc_parent_map_0, 1638c2ecf20Sopenharmony_ci .freq_tbl = ftbl_ext_mclk0_clk_src, 1648c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 1658c2ecf20Sopenharmony_ci .name = "ext_mclk0_clk_src", 1668c2ecf20Sopenharmony_ci .parent_data = lpass_core_cc_parent_data_0, 1678c2ecf20Sopenharmony_ci .num_parents = 2, 1688c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1698c2ecf20Sopenharmony_ci .ops = &clk_rcg2_ops, 1708c2ecf20Sopenharmony_ci }, 1718c2ecf20Sopenharmony_ci}; 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic struct clk_rcg2 lpaif_pri_clk_src = { 1748c2ecf20Sopenharmony_ci .cmd_rcgr = 0x10000, 1758c2ecf20Sopenharmony_ci .mnd_width = 16, 1768c2ecf20Sopenharmony_ci .hid_width = 5, 1778c2ecf20Sopenharmony_ci .parent_map = lpass_core_cc_parent_map_0, 1788c2ecf20Sopenharmony_ci .freq_tbl = ftbl_ext_lpaif_clk_src, 1798c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 1808c2ecf20Sopenharmony_ci .name = "lpaif_pri_clk_src", 1818c2ecf20Sopenharmony_ci .parent_data = lpass_core_cc_parent_data_0, 1828c2ecf20Sopenharmony_ci .num_parents = 2, 1838c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1848c2ecf20Sopenharmony_ci .ops = &clk_rcg2_ops, 1858c2ecf20Sopenharmony_ci }, 1868c2ecf20Sopenharmony_ci}; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_cistatic struct clk_rcg2 lpaif_sec_clk_src = { 1898c2ecf20Sopenharmony_ci .cmd_rcgr = 0x11000, 1908c2ecf20Sopenharmony_ci .mnd_width = 16, 1918c2ecf20Sopenharmony_ci .hid_width = 5, 1928c2ecf20Sopenharmony_ci .parent_map = lpass_core_cc_parent_map_0, 1938c2ecf20Sopenharmony_ci .freq_tbl = ftbl_ext_lpaif_clk_src, 1948c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 1958c2ecf20Sopenharmony_ci .name = "lpaif_sec_clk_src", 1968c2ecf20Sopenharmony_ci .parent_data = lpass_core_cc_parent_data_0, 1978c2ecf20Sopenharmony_ci .num_parents = 2, 1988c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1998c2ecf20Sopenharmony_ci .ops = &clk_rcg2_ops, 2008c2ecf20Sopenharmony_ci }, 2018c2ecf20Sopenharmony_ci}; 2028c2ecf20Sopenharmony_ci 2038c2ecf20Sopenharmony_cistatic struct clk_branch lpass_audio_core_ext_mclk0_clk = { 2048c2ecf20Sopenharmony_ci .halt_reg = 0x20014, 2058c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT, 2068c2ecf20Sopenharmony_ci .hwcg_reg = 0x20014, 2078c2ecf20Sopenharmony_ci .hwcg_bit = 1, 2088c2ecf20Sopenharmony_ci .clkr = { 2098c2ecf20Sopenharmony_ci .enable_reg = 0x20014, 2108c2ecf20Sopenharmony_ci .enable_mask = BIT(0), 2118c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 2128c2ecf20Sopenharmony_ci .name = "lpass_audio_core_ext_mclk0_clk", 2138c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 2148c2ecf20Sopenharmony_ci .hw = &ext_mclk0_clk_src.clkr.hw, 2158c2ecf20Sopenharmony_ci }, 2168c2ecf20Sopenharmony_ci .num_parents = 1, 2178c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 2188c2ecf20Sopenharmony_ci .ops = &clk_branch2_ops, 2198c2ecf20Sopenharmony_ci }, 2208c2ecf20Sopenharmony_ci }, 2218c2ecf20Sopenharmony_ci}; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic struct clk_branch lpass_audio_core_lpaif_pri_ibit_clk = { 2248c2ecf20Sopenharmony_ci .halt_reg = 0x10018, 2258c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT, 2268c2ecf20Sopenharmony_ci .hwcg_reg = 0x10018, 2278c2ecf20Sopenharmony_ci .hwcg_bit = 1, 2288c2ecf20Sopenharmony_ci .clkr = { 2298c2ecf20Sopenharmony_ci .enable_reg = 0x10018, 2308c2ecf20Sopenharmony_ci .enable_mask = BIT(0), 2318c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 2328c2ecf20Sopenharmony_ci .name = "lpass_audio_core_lpaif_pri_ibit_clk", 2338c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 2348c2ecf20Sopenharmony_ci .hw = &lpaif_pri_clk_src.clkr.hw, 2358c2ecf20Sopenharmony_ci }, 2368c2ecf20Sopenharmony_ci .num_parents = 1, 2378c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 2388c2ecf20Sopenharmony_ci .ops = &clk_branch2_ops, 2398c2ecf20Sopenharmony_ci }, 2408c2ecf20Sopenharmony_ci }, 2418c2ecf20Sopenharmony_ci}; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_cistatic struct clk_branch lpass_audio_core_lpaif_sec_ibit_clk = { 2448c2ecf20Sopenharmony_ci .halt_reg = 0x11018, 2458c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT, 2468c2ecf20Sopenharmony_ci .hwcg_reg = 0x11018, 2478c2ecf20Sopenharmony_ci .hwcg_bit = 1, 2488c2ecf20Sopenharmony_ci .clkr = { 2498c2ecf20Sopenharmony_ci .enable_reg = 0x11018, 2508c2ecf20Sopenharmony_ci .enable_mask = BIT(0), 2518c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 2528c2ecf20Sopenharmony_ci .name = "lpass_audio_core_lpaif_sec_ibit_clk", 2538c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 2548c2ecf20Sopenharmony_ci .hw = &lpaif_sec_clk_src.clkr.hw, 2558c2ecf20Sopenharmony_ci }, 2568c2ecf20Sopenharmony_ci .num_parents = 1, 2578c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 2588c2ecf20Sopenharmony_ci .ops = &clk_branch2_ops, 2598c2ecf20Sopenharmony_ci }, 2608c2ecf20Sopenharmony_ci }, 2618c2ecf20Sopenharmony_ci}; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic struct clk_branch lpass_audio_core_sysnoc_mport_core_clk = { 2648c2ecf20Sopenharmony_ci .halt_reg = 0x23000, 2658c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT, 2668c2ecf20Sopenharmony_ci .hwcg_reg = 0x23000, 2678c2ecf20Sopenharmony_ci .hwcg_bit = 1, 2688c2ecf20Sopenharmony_ci .clkr = { 2698c2ecf20Sopenharmony_ci .enable_reg = 0x23000, 2708c2ecf20Sopenharmony_ci .enable_mask = BIT(0), 2718c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 2728c2ecf20Sopenharmony_ci .name = "lpass_audio_core_sysnoc_mport_core_clk", 2738c2ecf20Sopenharmony_ci .parent_data = &(const struct clk_parent_data){ 2748c2ecf20Sopenharmony_ci .hw = &core_clk_src.clkr.hw, 2758c2ecf20Sopenharmony_ci }, 2768c2ecf20Sopenharmony_ci .num_parents = 1, 2778c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 2788c2ecf20Sopenharmony_ci .ops = &clk_branch2_ops, 2798c2ecf20Sopenharmony_ci }, 2808c2ecf20Sopenharmony_ci }, 2818c2ecf20Sopenharmony_ci}; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_cistatic struct clk_regmap *lpass_core_cc_sc7180_clocks[] = { 2848c2ecf20Sopenharmony_ci [EXT_MCLK0_CLK_SRC] = &ext_mclk0_clk_src.clkr, 2858c2ecf20Sopenharmony_ci [LPAIF_PRI_CLK_SRC] = &lpaif_pri_clk_src.clkr, 2868c2ecf20Sopenharmony_ci [LPAIF_SEC_CLK_SRC] = &lpaif_sec_clk_src.clkr, 2878c2ecf20Sopenharmony_ci [CORE_CLK_SRC] = &core_clk_src.clkr, 2888c2ecf20Sopenharmony_ci [LPASS_AUDIO_CORE_EXT_MCLK0_CLK] = &lpass_audio_core_ext_mclk0_clk.clkr, 2898c2ecf20Sopenharmony_ci [LPASS_AUDIO_CORE_LPAIF_PRI_IBIT_CLK] = 2908c2ecf20Sopenharmony_ci &lpass_audio_core_lpaif_pri_ibit_clk.clkr, 2918c2ecf20Sopenharmony_ci [LPASS_AUDIO_CORE_LPAIF_SEC_IBIT_CLK] = 2928c2ecf20Sopenharmony_ci &lpass_audio_core_lpaif_sec_ibit_clk.clkr, 2938c2ecf20Sopenharmony_ci [LPASS_AUDIO_CORE_SYSNOC_MPORT_CORE_CLK] = 2948c2ecf20Sopenharmony_ci &lpass_audio_core_sysnoc_mport_core_clk.clkr, 2958c2ecf20Sopenharmony_ci [LPASS_LPAAUDIO_DIG_PLL] = &lpass_lpaaudio_dig_pll.clkr, 2968c2ecf20Sopenharmony_ci [LPASS_LPAAUDIO_DIG_PLL_OUT_ODD] = &lpass_lpaaudio_dig_pll_out_odd.clkr, 2978c2ecf20Sopenharmony_ci}; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_cistatic struct gdsc lpass_pdc_hm_gdsc = { 3008c2ecf20Sopenharmony_ci .gdscr = 0x3090, 3018c2ecf20Sopenharmony_ci .pd = { 3028c2ecf20Sopenharmony_ci .name = "lpass_pdc_hm_gdsc", 3038c2ecf20Sopenharmony_ci }, 3048c2ecf20Sopenharmony_ci .pwrsts = PWRSTS_OFF_ON, 3058c2ecf20Sopenharmony_ci .flags = VOTABLE, 3068c2ecf20Sopenharmony_ci}; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_cistatic struct gdsc lpass_audio_hm_gdsc = { 3098c2ecf20Sopenharmony_ci .gdscr = 0x9090, 3108c2ecf20Sopenharmony_ci .pd = { 3118c2ecf20Sopenharmony_ci .name = "lpass_audio_hm_gdsc", 3128c2ecf20Sopenharmony_ci }, 3138c2ecf20Sopenharmony_ci .pwrsts = PWRSTS_OFF_ON, 3148c2ecf20Sopenharmony_ci}; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic struct gdsc lpass_core_hm_gdsc = { 3178c2ecf20Sopenharmony_ci .gdscr = 0x0, 3188c2ecf20Sopenharmony_ci .pd = { 3198c2ecf20Sopenharmony_ci .name = "lpass_core_hm_gdsc", 3208c2ecf20Sopenharmony_ci }, 3218c2ecf20Sopenharmony_ci .pwrsts = PWRSTS_OFF_ON, 3228c2ecf20Sopenharmony_ci .flags = RETAIN_FF_ENABLE, 3238c2ecf20Sopenharmony_ci}; 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic struct gdsc *lpass_core_hm_sc7180_gdscs[] = { 3268c2ecf20Sopenharmony_ci [LPASS_CORE_HM_GDSCR] = &lpass_core_hm_gdsc, 3278c2ecf20Sopenharmony_ci}; 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic struct gdsc *lpass_audio_hm_sc7180_gdscs[] = { 3308c2ecf20Sopenharmony_ci [LPASS_PDC_HM_GDSCR] = &lpass_pdc_hm_gdsc, 3318c2ecf20Sopenharmony_ci [LPASS_AUDIO_HM_GDSCR] = &lpass_audio_hm_gdsc, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic struct regmap_config lpass_core_cc_sc7180_regmap_config = { 3358c2ecf20Sopenharmony_ci .reg_bits = 32, 3368c2ecf20Sopenharmony_ci .reg_stride = 4, 3378c2ecf20Sopenharmony_ci .val_bits = 32, 3388c2ecf20Sopenharmony_ci .fast_io = true, 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic const struct qcom_cc_desc lpass_core_hm_sc7180_desc = { 3428c2ecf20Sopenharmony_ci .config = &lpass_core_cc_sc7180_regmap_config, 3438c2ecf20Sopenharmony_ci .gdscs = lpass_core_hm_sc7180_gdscs, 3448c2ecf20Sopenharmony_ci .num_gdscs = ARRAY_SIZE(lpass_core_hm_sc7180_gdscs), 3458c2ecf20Sopenharmony_ci}; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic const struct qcom_cc_desc lpass_core_cc_sc7180_desc = { 3488c2ecf20Sopenharmony_ci .config = &lpass_core_cc_sc7180_regmap_config, 3498c2ecf20Sopenharmony_ci .clks = lpass_core_cc_sc7180_clocks, 3508c2ecf20Sopenharmony_ci .num_clks = ARRAY_SIZE(lpass_core_cc_sc7180_clocks), 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic const struct qcom_cc_desc lpass_audio_hm_sc7180_desc = { 3548c2ecf20Sopenharmony_ci .config = &lpass_core_cc_sc7180_regmap_config, 3558c2ecf20Sopenharmony_ci .gdscs = lpass_audio_hm_sc7180_gdscs, 3568c2ecf20Sopenharmony_ci .num_gdscs = ARRAY_SIZE(lpass_audio_hm_sc7180_gdscs), 3578c2ecf20Sopenharmony_ci}; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic int lpass_core_cc_sc7180_probe(struct platform_device *pdev) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci const struct qcom_cc_desc *desc; 3628c2ecf20Sopenharmony_ci struct regmap *regmap; 3638c2ecf20Sopenharmony_ci int ret; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci lpass_core_cc_sc7180_regmap_config.name = "lpass_audio_cc"; 3668c2ecf20Sopenharmony_ci desc = &lpass_audio_hm_sc7180_desc; 3678c2ecf20Sopenharmony_ci ret = qcom_cc_probe_by_index(pdev, 1, desc); 3688c2ecf20Sopenharmony_ci if (ret) 3698c2ecf20Sopenharmony_ci return ret; 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_ci lpass_core_cc_sc7180_regmap_config.name = "lpass_core_cc"; 3728c2ecf20Sopenharmony_ci regmap = qcom_cc_map(pdev, &lpass_core_cc_sc7180_desc); 3738c2ecf20Sopenharmony_ci if (IS_ERR(regmap)) 3748c2ecf20Sopenharmony_ci return PTR_ERR(regmap); 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * Keep the CLK always-ON 3788c2ecf20Sopenharmony_ci * LPASS_AUDIO_CORE_SYSNOC_SWAY_CORE_CLK 3798c2ecf20Sopenharmony_ci */ 3808c2ecf20Sopenharmony_ci regmap_update_bits(regmap, 0x24000, BIT(0), BIT(0)); 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci /* PLL settings */ 3838c2ecf20Sopenharmony_ci regmap_write(regmap, 0x1008, 0x20); 3848c2ecf20Sopenharmony_ci regmap_update_bits(regmap, 0x1014, BIT(0), BIT(0)); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci clk_fabia_pll_configure(&lpass_lpaaudio_dig_pll, regmap, 3878c2ecf20Sopenharmony_ci &lpass_lpaaudio_dig_pll_config); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci return qcom_cc_really_probe(pdev, &lpass_core_cc_sc7180_desc, regmap); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic int lpass_hm_core_probe(struct platform_device *pdev) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci const struct qcom_cc_desc *desc; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci lpass_core_cc_sc7180_regmap_config.name = "lpass_hm_core"; 3978c2ecf20Sopenharmony_ci desc = &lpass_core_hm_sc7180_desc; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci return qcom_cc_probe_by_index(pdev, 0, desc); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic const struct of_device_id lpass_core_cc_sc7180_match_table[] = { 4038c2ecf20Sopenharmony_ci { 4048c2ecf20Sopenharmony_ci .compatible = "qcom,sc7180-lpasshm", 4058c2ecf20Sopenharmony_ci .data = lpass_hm_core_probe, 4068c2ecf20Sopenharmony_ci }, 4078c2ecf20Sopenharmony_ci { 4088c2ecf20Sopenharmony_ci .compatible = "qcom,sc7180-lpasscorecc", 4098c2ecf20Sopenharmony_ci .data = lpass_core_cc_sc7180_probe, 4108c2ecf20Sopenharmony_ci }, 4118c2ecf20Sopenharmony_ci { } 4128c2ecf20Sopenharmony_ci}; 4138c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, lpass_core_cc_sc7180_match_table); 4148c2ecf20Sopenharmony_ci 4158c2ecf20Sopenharmony_cistatic int lpass_core_sc7180_probe(struct platform_device *pdev) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci int (*clk_probe)(struct platform_device *p); 4188c2ecf20Sopenharmony_ci int ret; 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci pm_runtime_enable(&pdev->dev); 4218c2ecf20Sopenharmony_ci ret = pm_clk_create(&pdev->dev); 4228c2ecf20Sopenharmony_ci if (ret) 4238c2ecf20Sopenharmony_ci goto disable_pm_runtime; 4248c2ecf20Sopenharmony_ci 4258c2ecf20Sopenharmony_ci ret = pm_clk_add(&pdev->dev, "iface"); 4268c2ecf20Sopenharmony_ci if (ret < 0) { 4278c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "failed to acquire iface clock\n"); 4288c2ecf20Sopenharmony_ci goto destroy_pm_clk; 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci ret = -EINVAL; 4328c2ecf20Sopenharmony_ci clk_probe = of_device_get_match_data(&pdev->dev); 4338c2ecf20Sopenharmony_ci if (!clk_probe) 4348c2ecf20Sopenharmony_ci goto destroy_pm_clk; 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_ci ret = clk_probe(pdev); 4378c2ecf20Sopenharmony_ci if (ret) 4388c2ecf20Sopenharmony_ci goto destroy_pm_clk; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_ci return 0; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cidestroy_pm_clk: 4438c2ecf20Sopenharmony_ci pm_clk_destroy(&pdev->dev); 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_cidisable_pm_runtime: 4468c2ecf20Sopenharmony_ci pm_runtime_disable(&pdev->dev); 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci return ret; 4498c2ecf20Sopenharmony_ci} 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_cistatic const struct dev_pm_ops lpass_core_cc_pm_ops = { 4528c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL) 4538c2ecf20Sopenharmony_ci}; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic struct platform_driver lpass_core_cc_sc7180_driver = { 4568c2ecf20Sopenharmony_ci .probe = lpass_core_sc7180_probe, 4578c2ecf20Sopenharmony_ci .driver = { 4588c2ecf20Sopenharmony_ci .name = "lpass_core_cc-sc7180", 4598c2ecf20Sopenharmony_ci .of_match_table = lpass_core_cc_sc7180_match_table, 4608c2ecf20Sopenharmony_ci .pm = &lpass_core_cc_pm_ops, 4618c2ecf20Sopenharmony_ci }, 4628c2ecf20Sopenharmony_ci}; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic int __init lpass_core_cc_sc7180_init(void) 4658c2ecf20Sopenharmony_ci{ 4668c2ecf20Sopenharmony_ci return platform_driver_register(&lpass_core_cc_sc7180_driver); 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_cisubsys_initcall(lpass_core_cc_sc7180_init); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_cistatic void __exit lpass_core_cc_sc7180_exit(void) 4718c2ecf20Sopenharmony_ci{ 4728c2ecf20Sopenharmony_ci platform_driver_unregister(&lpass_core_cc_sc7180_driver); 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_cimodule_exit(lpass_core_cc_sc7180_exit); 4758c2ecf20Sopenharmony_ci 4768c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("QTI LPASS_CORE_CC SC7180 Driver"); 4778c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 478