18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014, The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) BayLibre, SAS. 58c2ecf20Sopenharmony_ci * Author : Neil Armstrong <narmstrong@baylibre.com> 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <linux/kernel.h> 98c2ecf20Sopenharmony_ci#include <linux/bitops.h> 108c2ecf20Sopenharmony_ci#include <linux/err.h> 118c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/of_device.h> 158c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 168c2ecf20Sopenharmony_ci#include <linux/regmap.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include <dt-bindings/clock/qcom,lcc-mdm9615.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "common.h" 218c2ecf20Sopenharmony_ci#include "clk-regmap.h" 228c2ecf20Sopenharmony_ci#include "clk-pll.h" 238c2ecf20Sopenharmony_ci#include "clk-rcg.h" 248c2ecf20Sopenharmony_ci#include "clk-branch.h" 258c2ecf20Sopenharmony_ci#include "clk-regmap-divider.h" 268c2ecf20Sopenharmony_ci#include "clk-regmap-mux.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic struct clk_pll pll4 = { 298c2ecf20Sopenharmony_ci .l_reg = 0x4, 308c2ecf20Sopenharmony_ci .m_reg = 0x8, 318c2ecf20Sopenharmony_ci .n_reg = 0xc, 328c2ecf20Sopenharmony_ci .config_reg = 0x14, 338c2ecf20Sopenharmony_ci .mode_reg = 0x0, 348c2ecf20Sopenharmony_ci .status_reg = 0x18, 358c2ecf20Sopenharmony_ci .status_bit = 16, 368c2ecf20Sopenharmony_ci .clkr.hw.init = &(struct clk_init_data){ 378c2ecf20Sopenharmony_ci .name = "pll4", 388c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ "cxo" }, 398c2ecf20Sopenharmony_ci .num_parents = 1, 408c2ecf20Sopenharmony_ci .ops = &clk_pll_ops, 418c2ecf20Sopenharmony_ci }, 428c2ecf20Sopenharmony_ci}; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_cienum { 458c2ecf20Sopenharmony_ci P_CXO, 468c2ecf20Sopenharmony_ci P_PLL4, 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_cistatic const struct parent_map lcc_cxo_pll4_map[] = { 508c2ecf20Sopenharmony_ci { P_CXO, 0 }, 518c2ecf20Sopenharmony_ci { P_PLL4, 2 } 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistatic const char * const lcc_cxo_pll4[] = { 558c2ecf20Sopenharmony_ci "cxo", 568c2ecf20Sopenharmony_ci "pll4_vote", 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cistatic struct freq_tbl clk_tbl_aif_osr_492[] = { 608c2ecf20Sopenharmony_ci { 512000, P_PLL4, 4, 1, 240 }, 618c2ecf20Sopenharmony_ci { 768000, P_PLL4, 4, 1, 160 }, 628c2ecf20Sopenharmony_ci { 1024000, P_PLL4, 4, 1, 120 }, 638c2ecf20Sopenharmony_ci { 1536000, P_PLL4, 4, 1, 80 }, 648c2ecf20Sopenharmony_ci { 2048000, P_PLL4, 4, 1, 60 }, 658c2ecf20Sopenharmony_ci { 3072000, P_PLL4, 4, 1, 40 }, 668c2ecf20Sopenharmony_ci { 4096000, P_PLL4, 4, 1, 30 }, 678c2ecf20Sopenharmony_ci { 6144000, P_PLL4, 4, 1, 20 }, 688c2ecf20Sopenharmony_ci { 8192000, P_PLL4, 4, 1, 15 }, 698c2ecf20Sopenharmony_ci { 12288000, P_PLL4, 4, 1, 10 }, 708c2ecf20Sopenharmony_ci { 24576000, P_PLL4, 4, 1, 5 }, 718c2ecf20Sopenharmony_ci { 27000000, P_CXO, 1, 0, 0 }, 728c2ecf20Sopenharmony_ci { } 738c2ecf20Sopenharmony_ci}; 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic struct freq_tbl clk_tbl_aif_osr_393[] = { 768c2ecf20Sopenharmony_ci { 512000, P_PLL4, 4, 1, 192 }, 778c2ecf20Sopenharmony_ci { 768000, P_PLL4, 4, 1, 128 }, 788c2ecf20Sopenharmony_ci { 1024000, P_PLL4, 4, 1, 96 }, 798c2ecf20Sopenharmony_ci { 1536000, P_PLL4, 4, 1, 64 }, 808c2ecf20Sopenharmony_ci { 2048000, P_PLL4, 4, 1, 48 }, 818c2ecf20Sopenharmony_ci { 3072000, P_PLL4, 4, 1, 32 }, 828c2ecf20Sopenharmony_ci { 4096000, P_PLL4, 4, 1, 24 }, 838c2ecf20Sopenharmony_ci { 6144000, P_PLL4, 4, 1, 16 }, 848c2ecf20Sopenharmony_ci { 8192000, P_PLL4, 4, 1, 12 }, 858c2ecf20Sopenharmony_ci { 12288000, P_PLL4, 4, 1, 8 }, 868c2ecf20Sopenharmony_ci { 24576000, P_PLL4, 4, 1, 4 }, 878c2ecf20Sopenharmony_ci { 27000000, P_CXO, 1, 0, 0 }, 888c2ecf20Sopenharmony_ci { } 898c2ecf20Sopenharmony_ci}; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_cistatic struct clk_rcg mi2s_osr_src = { 928c2ecf20Sopenharmony_ci .ns_reg = 0x48, 938c2ecf20Sopenharmony_ci .md_reg = 0x4c, 948c2ecf20Sopenharmony_ci .mn = { 958c2ecf20Sopenharmony_ci .mnctr_en_bit = 8, 968c2ecf20Sopenharmony_ci .mnctr_reset_bit = 7, 978c2ecf20Sopenharmony_ci .mnctr_mode_shift = 5, 988c2ecf20Sopenharmony_ci .n_val_shift = 24, 998c2ecf20Sopenharmony_ci .m_val_shift = 8, 1008c2ecf20Sopenharmony_ci .width = 8, 1018c2ecf20Sopenharmony_ci }, 1028c2ecf20Sopenharmony_ci .p = { 1038c2ecf20Sopenharmony_ci .pre_div_shift = 3, 1048c2ecf20Sopenharmony_ci .pre_div_width = 2, 1058c2ecf20Sopenharmony_ci }, 1068c2ecf20Sopenharmony_ci .s = { 1078c2ecf20Sopenharmony_ci .src_sel_shift = 0, 1088c2ecf20Sopenharmony_ci .parent_map = lcc_cxo_pll4_map, 1098c2ecf20Sopenharmony_ci }, 1108c2ecf20Sopenharmony_ci .freq_tbl = clk_tbl_aif_osr_393, 1118c2ecf20Sopenharmony_ci .clkr = { 1128c2ecf20Sopenharmony_ci .enable_reg = 0x48, 1138c2ecf20Sopenharmony_ci .enable_mask = BIT(9), 1148c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 1158c2ecf20Sopenharmony_ci .name = "mi2s_osr_src", 1168c2ecf20Sopenharmony_ci .parent_names = lcc_cxo_pll4, 1178c2ecf20Sopenharmony_ci .num_parents = 2, 1188c2ecf20Sopenharmony_ci .ops = &clk_rcg_ops, 1198c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_GATE, 1208c2ecf20Sopenharmony_ci }, 1218c2ecf20Sopenharmony_ci }, 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic const char * const lcc_mi2s_parents[] = { 1258c2ecf20Sopenharmony_ci "mi2s_osr_src", 1268c2ecf20Sopenharmony_ci}; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic struct clk_branch mi2s_osr_clk = { 1298c2ecf20Sopenharmony_ci .halt_reg = 0x50, 1308c2ecf20Sopenharmony_ci .halt_bit = 1, 1318c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, 1328c2ecf20Sopenharmony_ci .clkr = { 1338c2ecf20Sopenharmony_ci .enable_reg = 0x48, 1348c2ecf20Sopenharmony_ci .enable_mask = BIT(17), 1358c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 1368c2ecf20Sopenharmony_ci .name = "mi2s_osr_clk", 1378c2ecf20Sopenharmony_ci .parent_names = lcc_mi2s_parents, 1388c2ecf20Sopenharmony_ci .num_parents = 1, 1398c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, 1408c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1418c2ecf20Sopenharmony_ci }, 1428c2ecf20Sopenharmony_ci }, 1438c2ecf20Sopenharmony_ci}; 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_cistatic struct clk_regmap_div mi2s_div_clk = { 1468c2ecf20Sopenharmony_ci .reg = 0x48, 1478c2ecf20Sopenharmony_ci .shift = 10, 1488c2ecf20Sopenharmony_ci .width = 4, 1498c2ecf20Sopenharmony_ci .clkr = { 1508c2ecf20Sopenharmony_ci .enable_reg = 0x48, 1518c2ecf20Sopenharmony_ci .enable_mask = BIT(15), 1528c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 1538c2ecf20Sopenharmony_ci .name = "mi2s_div_clk", 1548c2ecf20Sopenharmony_ci .parent_names = lcc_mi2s_parents, 1558c2ecf20Sopenharmony_ci .num_parents = 1, 1568c2ecf20Sopenharmony_ci .ops = &clk_regmap_div_ops, 1578c2ecf20Sopenharmony_ci }, 1588c2ecf20Sopenharmony_ci }, 1598c2ecf20Sopenharmony_ci}; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic struct clk_branch mi2s_bit_div_clk = { 1628c2ecf20Sopenharmony_ci .halt_reg = 0x50, 1638c2ecf20Sopenharmony_ci .halt_bit = 0, 1648c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, 1658c2ecf20Sopenharmony_ci .clkr = { 1668c2ecf20Sopenharmony_ci .enable_reg = 0x48, 1678c2ecf20Sopenharmony_ci .enable_mask = BIT(15), 1688c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 1698c2ecf20Sopenharmony_ci .name = "mi2s_bit_div_clk", 1708c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ "mi2s_div_clk" }, 1718c2ecf20Sopenharmony_ci .num_parents = 1, 1728c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, 1738c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1748c2ecf20Sopenharmony_ci }, 1758c2ecf20Sopenharmony_ci }, 1768c2ecf20Sopenharmony_ci}; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic struct clk_regmap_mux mi2s_bit_clk = { 1798c2ecf20Sopenharmony_ci .reg = 0x48, 1808c2ecf20Sopenharmony_ci .shift = 14, 1818c2ecf20Sopenharmony_ci .width = 1, 1828c2ecf20Sopenharmony_ci .clkr = { 1838c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 1848c2ecf20Sopenharmony_ci .name = "mi2s_bit_clk", 1858c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ 1868c2ecf20Sopenharmony_ci "mi2s_bit_div_clk", 1878c2ecf20Sopenharmony_ci "mi2s_codec_clk", 1888c2ecf20Sopenharmony_ci }, 1898c2ecf20Sopenharmony_ci .num_parents = 2, 1908c2ecf20Sopenharmony_ci .ops = &clk_regmap_mux_closest_ops, 1918c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 1928c2ecf20Sopenharmony_ci }, 1938c2ecf20Sopenharmony_ci }, 1948c2ecf20Sopenharmony_ci}; 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci#define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr) \ 1978c2ecf20Sopenharmony_cistatic struct clk_rcg prefix##_osr_src = { \ 1988c2ecf20Sopenharmony_ci .ns_reg = _ns, \ 1998c2ecf20Sopenharmony_ci .md_reg = _md, \ 2008c2ecf20Sopenharmony_ci .mn = { \ 2018c2ecf20Sopenharmony_ci .mnctr_en_bit = 8, \ 2028c2ecf20Sopenharmony_ci .mnctr_reset_bit = 7, \ 2038c2ecf20Sopenharmony_ci .mnctr_mode_shift = 5, \ 2048c2ecf20Sopenharmony_ci .n_val_shift = 24, \ 2058c2ecf20Sopenharmony_ci .m_val_shift = 8, \ 2068c2ecf20Sopenharmony_ci .width = 8, \ 2078c2ecf20Sopenharmony_ci }, \ 2088c2ecf20Sopenharmony_ci .p = { \ 2098c2ecf20Sopenharmony_ci .pre_div_shift = 3, \ 2108c2ecf20Sopenharmony_ci .pre_div_width = 2, \ 2118c2ecf20Sopenharmony_ci }, \ 2128c2ecf20Sopenharmony_ci .s = { \ 2138c2ecf20Sopenharmony_ci .src_sel_shift = 0, \ 2148c2ecf20Sopenharmony_ci .parent_map = lcc_cxo_pll4_map, \ 2158c2ecf20Sopenharmony_ci }, \ 2168c2ecf20Sopenharmony_ci .freq_tbl = clk_tbl_aif_osr_393, \ 2178c2ecf20Sopenharmony_ci .clkr = { \ 2188c2ecf20Sopenharmony_ci .enable_reg = _ns, \ 2198c2ecf20Sopenharmony_ci .enable_mask = BIT(9), \ 2208c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ \ 2218c2ecf20Sopenharmony_ci .name = #prefix "_osr_src", \ 2228c2ecf20Sopenharmony_ci .parent_names = lcc_cxo_pll4, \ 2238c2ecf20Sopenharmony_ci .num_parents = 2, \ 2248c2ecf20Sopenharmony_ci .ops = &clk_rcg_ops, \ 2258c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_GATE, \ 2268c2ecf20Sopenharmony_ci }, \ 2278c2ecf20Sopenharmony_ci }, \ 2288c2ecf20Sopenharmony_ci}; \ 2298c2ecf20Sopenharmony_ci \ 2308c2ecf20Sopenharmony_cistatic const char * const lcc_##prefix##_parents[] = { \ 2318c2ecf20Sopenharmony_ci #prefix "_osr_src", \ 2328c2ecf20Sopenharmony_ci}; \ 2338c2ecf20Sopenharmony_ci \ 2348c2ecf20Sopenharmony_cistatic struct clk_branch prefix##_osr_clk = { \ 2358c2ecf20Sopenharmony_ci .halt_reg = hr, \ 2368c2ecf20Sopenharmony_ci .halt_bit = 1, \ 2378c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, \ 2388c2ecf20Sopenharmony_ci .clkr = { \ 2398c2ecf20Sopenharmony_ci .enable_reg = _ns, \ 2408c2ecf20Sopenharmony_ci .enable_mask = BIT(21), \ 2418c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ \ 2428c2ecf20Sopenharmony_ci .name = #prefix "_osr_clk", \ 2438c2ecf20Sopenharmony_ci .parent_names = lcc_##prefix##_parents, \ 2448c2ecf20Sopenharmony_ci .num_parents = 1, \ 2458c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, \ 2468c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, \ 2478c2ecf20Sopenharmony_ci }, \ 2488c2ecf20Sopenharmony_ci }, \ 2498c2ecf20Sopenharmony_ci}; \ 2508c2ecf20Sopenharmony_ci \ 2518c2ecf20Sopenharmony_cistatic struct clk_regmap_div prefix##_div_clk = { \ 2528c2ecf20Sopenharmony_ci .reg = _ns, \ 2538c2ecf20Sopenharmony_ci .shift = 10, \ 2548c2ecf20Sopenharmony_ci .width = 8, \ 2558c2ecf20Sopenharmony_ci .clkr = { \ 2568c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ \ 2578c2ecf20Sopenharmony_ci .name = #prefix "_div_clk", \ 2588c2ecf20Sopenharmony_ci .parent_names = lcc_##prefix##_parents, \ 2598c2ecf20Sopenharmony_ci .num_parents = 1, \ 2608c2ecf20Sopenharmony_ci .ops = &clk_regmap_div_ops, \ 2618c2ecf20Sopenharmony_ci }, \ 2628c2ecf20Sopenharmony_ci }, \ 2638c2ecf20Sopenharmony_ci}; \ 2648c2ecf20Sopenharmony_ci \ 2658c2ecf20Sopenharmony_cistatic struct clk_branch prefix##_bit_div_clk = { \ 2668c2ecf20Sopenharmony_ci .halt_reg = hr, \ 2678c2ecf20Sopenharmony_ci .halt_bit = 0, \ 2688c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, \ 2698c2ecf20Sopenharmony_ci .clkr = { \ 2708c2ecf20Sopenharmony_ci .enable_reg = _ns, \ 2718c2ecf20Sopenharmony_ci .enable_mask = BIT(19), \ 2728c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ \ 2738c2ecf20Sopenharmony_ci .name = #prefix "_bit_div_clk", \ 2748c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ \ 2758c2ecf20Sopenharmony_ci #prefix "_div_clk" \ 2768c2ecf20Sopenharmony_ci }, \ 2778c2ecf20Sopenharmony_ci .num_parents = 1, \ 2788c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, \ 2798c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, \ 2808c2ecf20Sopenharmony_ci }, \ 2818c2ecf20Sopenharmony_ci }, \ 2828c2ecf20Sopenharmony_ci}; \ 2838c2ecf20Sopenharmony_ci \ 2848c2ecf20Sopenharmony_cistatic struct clk_regmap_mux prefix##_bit_clk = { \ 2858c2ecf20Sopenharmony_ci .reg = _ns, \ 2868c2ecf20Sopenharmony_ci .shift = 18, \ 2878c2ecf20Sopenharmony_ci .width = 1, \ 2888c2ecf20Sopenharmony_ci .clkr = { \ 2898c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ \ 2908c2ecf20Sopenharmony_ci .name = #prefix "_bit_clk", \ 2918c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ \ 2928c2ecf20Sopenharmony_ci #prefix "_bit_div_clk", \ 2938c2ecf20Sopenharmony_ci #prefix "_codec_clk", \ 2948c2ecf20Sopenharmony_ci }, \ 2958c2ecf20Sopenharmony_ci .num_parents = 2, \ 2968c2ecf20Sopenharmony_ci .ops = &clk_regmap_mux_closest_ops, \ 2978c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, \ 2988c2ecf20Sopenharmony_ci }, \ 2998c2ecf20Sopenharmony_ci }, \ 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ciCLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68); 3038c2ecf20Sopenharmony_ciCLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80); 3048c2ecf20Sopenharmony_ciCLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74); 3058c2ecf20Sopenharmony_ciCLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c); 3068c2ecf20Sopenharmony_ci 3078c2ecf20Sopenharmony_cistatic struct freq_tbl clk_tbl_pcm_492[] = { 3088c2ecf20Sopenharmony_ci { 256000, P_PLL4, 4, 1, 480 }, 3098c2ecf20Sopenharmony_ci { 512000, P_PLL4, 4, 1, 240 }, 3108c2ecf20Sopenharmony_ci { 768000, P_PLL4, 4, 1, 160 }, 3118c2ecf20Sopenharmony_ci { 1024000, P_PLL4, 4, 1, 120 }, 3128c2ecf20Sopenharmony_ci { 1536000, P_PLL4, 4, 1, 80 }, 3138c2ecf20Sopenharmony_ci { 2048000, P_PLL4, 4, 1, 60 }, 3148c2ecf20Sopenharmony_ci { 3072000, P_PLL4, 4, 1, 40 }, 3158c2ecf20Sopenharmony_ci { 4096000, P_PLL4, 4, 1, 30 }, 3168c2ecf20Sopenharmony_ci { 6144000, P_PLL4, 4, 1, 20 }, 3178c2ecf20Sopenharmony_ci { 8192000, P_PLL4, 4, 1, 15 }, 3188c2ecf20Sopenharmony_ci { 12288000, P_PLL4, 4, 1, 10 }, 3198c2ecf20Sopenharmony_ci { 24576000, P_PLL4, 4, 1, 5 }, 3208c2ecf20Sopenharmony_ci { 27000000, P_CXO, 1, 0, 0 }, 3218c2ecf20Sopenharmony_ci { } 3228c2ecf20Sopenharmony_ci}; 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic struct freq_tbl clk_tbl_pcm_393[] = { 3258c2ecf20Sopenharmony_ci { 256000, P_PLL4, 4, 1, 384 }, 3268c2ecf20Sopenharmony_ci { 512000, P_PLL4, 4, 1, 192 }, 3278c2ecf20Sopenharmony_ci { 768000, P_PLL4, 4, 1, 128 }, 3288c2ecf20Sopenharmony_ci { 1024000, P_PLL4, 4, 1, 96 }, 3298c2ecf20Sopenharmony_ci { 1536000, P_PLL4, 4, 1, 64 }, 3308c2ecf20Sopenharmony_ci { 2048000, P_PLL4, 4, 1, 48 }, 3318c2ecf20Sopenharmony_ci { 3072000, P_PLL4, 4, 1, 32 }, 3328c2ecf20Sopenharmony_ci { 4096000, P_PLL4, 4, 1, 24 }, 3338c2ecf20Sopenharmony_ci { 6144000, P_PLL4, 4, 1, 16 }, 3348c2ecf20Sopenharmony_ci { 8192000, P_PLL4, 4, 1, 12 }, 3358c2ecf20Sopenharmony_ci { 12288000, P_PLL4, 4, 1, 8 }, 3368c2ecf20Sopenharmony_ci { 24576000, P_PLL4, 4, 1, 4 }, 3378c2ecf20Sopenharmony_ci { 27000000, P_CXO, 1, 0, 0 }, 3388c2ecf20Sopenharmony_ci { } 3398c2ecf20Sopenharmony_ci}; 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic struct clk_rcg pcm_src = { 3428c2ecf20Sopenharmony_ci .ns_reg = 0x54, 3438c2ecf20Sopenharmony_ci .md_reg = 0x58, 3448c2ecf20Sopenharmony_ci .mn = { 3458c2ecf20Sopenharmony_ci .mnctr_en_bit = 8, 3468c2ecf20Sopenharmony_ci .mnctr_reset_bit = 7, 3478c2ecf20Sopenharmony_ci .mnctr_mode_shift = 5, 3488c2ecf20Sopenharmony_ci .n_val_shift = 16, 3498c2ecf20Sopenharmony_ci .m_val_shift = 16, 3508c2ecf20Sopenharmony_ci .width = 16, 3518c2ecf20Sopenharmony_ci }, 3528c2ecf20Sopenharmony_ci .p = { 3538c2ecf20Sopenharmony_ci .pre_div_shift = 3, 3548c2ecf20Sopenharmony_ci .pre_div_width = 2, 3558c2ecf20Sopenharmony_ci }, 3568c2ecf20Sopenharmony_ci .s = { 3578c2ecf20Sopenharmony_ci .src_sel_shift = 0, 3588c2ecf20Sopenharmony_ci .parent_map = lcc_cxo_pll4_map, 3598c2ecf20Sopenharmony_ci }, 3608c2ecf20Sopenharmony_ci .freq_tbl = clk_tbl_pcm_393, 3618c2ecf20Sopenharmony_ci .clkr = { 3628c2ecf20Sopenharmony_ci .enable_reg = 0x54, 3638c2ecf20Sopenharmony_ci .enable_mask = BIT(9), 3648c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 3658c2ecf20Sopenharmony_ci .name = "pcm_src", 3668c2ecf20Sopenharmony_ci .parent_names = lcc_cxo_pll4, 3678c2ecf20Sopenharmony_ci .num_parents = 2, 3688c2ecf20Sopenharmony_ci .ops = &clk_rcg_ops, 3698c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_GATE, 3708c2ecf20Sopenharmony_ci }, 3718c2ecf20Sopenharmony_ci }, 3728c2ecf20Sopenharmony_ci}; 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_cistatic struct clk_branch pcm_clk_out = { 3758c2ecf20Sopenharmony_ci .halt_reg = 0x5c, 3768c2ecf20Sopenharmony_ci .halt_bit = 0, 3778c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, 3788c2ecf20Sopenharmony_ci .clkr = { 3798c2ecf20Sopenharmony_ci .enable_reg = 0x54, 3808c2ecf20Sopenharmony_ci .enable_mask = BIT(11), 3818c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 3828c2ecf20Sopenharmony_ci .name = "pcm_clk_out", 3838c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ "pcm_src" }, 3848c2ecf20Sopenharmony_ci .num_parents = 1, 3858c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, 3868c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 3878c2ecf20Sopenharmony_ci }, 3888c2ecf20Sopenharmony_ci }, 3898c2ecf20Sopenharmony_ci}; 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic struct clk_regmap_mux pcm_clk = { 3928c2ecf20Sopenharmony_ci .reg = 0x54, 3938c2ecf20Sopenharmony_ci .shift = 10, 3948c2ecf20Sopenharmony_ci .width = 1, 3958c2ecf20Sopenharmony_ci .clkr = { 3968c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 3978c2ecf20Sopenharmony_ci .name = "pcm_clk", 3988c2ecf20Sopenharmony_ci .parent_names = (const char *[]){ 3998c2ecf20Sopenharmony_ci "pcm_clk_out", 4008c2ecf20Sopenharmony_ci "pcm_codec_clk", 4018c2ecf20Sopenharmony_ci }, 4028c2ecf20Sopenharmony_ci .num_parents = 2, 4038c2ecf20Sopenharmony_ci .ops = &clk_regmap_mux_closest_ops, 4048c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 4058c2ecf20Sopenharmony_ci }, 4068c2ecf20Sopenharmony_ci }, 4078c2ecf20Sopenharmony_ci}; 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic struct clk_rcg slimbus_src = { 4108c2ecf20Sopenharmony_ci .ns_reg = 0xcc, 4118c2ecf20Sopenharmony_ci .md_reg = 0xd0, 4128c2ecf20Sopenharmony_ci .mn = { 4138c2ecf20Sopenharmony_ci .mnctr_en_bit = 8, 4148c2ecf20Sopenharmony_ci .mnctr_reset_bit = 7, 4158c2ecf20Sopenharmony_ci .mnctr_mode_shift = 5, 4168c2ecf20Sopenharmony_ci .n_val_shift = 24, 4178c2ecf20Sopenharmony_ci .m_val_shift = 8, 4188c2ecf20Sopenharmony_ci .width = 8, 4198c2ecf20Sopenharmony_ci }, 4208c2ecf20Sopenharmony_ci .p = { 4218c2ecf20Sopenharmony_ci .pre_div_shift = 3, 4228c2ecf20Sopenharmony_ci .pre_div_width = 2, 4238c2ecf20Sopenharmony_ci }, 4248c2ecf20Sopenharmony_ci .s = { 4258c2ecf20Sopenharmony_ci .src_sel_shift = 0, 4268c2ecf20Sopenharmony_ci .parent_map = lcc_cxo_pll4_map, 4278c2ecf20Sopenharmony_ci }, 4288c2ecf20Sopenharmony_ci .freq_tbl = clk_tbl_aif_osr_393, 4298c2ecf20Sopenharmony_ci .clkr = { 4308c2ecf20Sopenharmony_ci .enable_reg = 0xcc, 4318c2ecf20Sopenharmony_ci .enable_mask = BIT(9), 4328c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 4338c2ecf20Sopenharmony_ci .name = "slimbus_src", 4348c2ecf20Sopenharmony_ci .parent_names = lcc_cxo_pll4, 4358c2ecf20Sopenharmony_ci .num_parents = 2, 4368c2ecf20Sopenharmony_ci .ops = &clk_rcg_ops, 4378c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_GATE, 4388c2ecf20Sopenharmony_ci }, 4398c2ecf20Sopenharmony_ci }, 4408c2ecf20Sopenharmony_ci}; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_cistatic const char * const lcc_slimbus_parents[] = { 4438c2ecf20Sopenharmony_ci "slimbus_src", 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic struct clk_branch audio_slimbus_clk = { 4478c2ecf20Sopenharmony_ci .halt_reg = 0xd4, 4488c2ecf20Sopenharmony_ci .halt_bit = 0, 4498c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, 4508c2ecf20Sopenharmony_ci .clkr = { 4518c2ecf20Sopenharmony_ci .enable_reg = 0xcc, 4528c2ecf20Sopenharmony_ci .enable_mask = BIT(10), 4538c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 4548c2ecf20Sopenharmony_ci .name = "audio_slimbus_clk", 4558c2ecf20Sopenharmony_ci .parent_names = lcc_slimbus_parents, 4568c2ecf20Sopenharmony_ci .num_parents = 1, 4578c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, 4588c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 4598c2ecf20Sopenharmony_ci }, 4608c2ecf20Sopenharmony_ci }, 4618c2ecf20Sopenharmony_ci}; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_cistatic struct clk_branch sps_slimbus_clk = { 4648c2ecf20Sopenharmony_ci .halt_reg = 0xd4, 4658c2ecf20Sopenharmony_ci .halt_bit = 1, 4668c2ecf20Sopenharmony_ci .halt_check = BRANCH_HALT_ENABLE, 4678c2ecf20Sopenharmony_ci .clkr = { 4688c2ecf20Sopenharmony_ci .enable_reg = 0xcc, 4698c2ecf20Sopenharmony_ci .enable_mask = BIT(12), 4708c2ecf20Sopenharmony_ci .hw.init = &(struct clk_init_data){ 4718c2ecf20Sopenharmony_ci .name = "sps_slimbus_clk", 4728c2ecf20Sopenharmony_ci .parent_names = lcc_slimbus_parents, 4738c2ecf20Sopenharmony_ci .num_parents = 1, 4748c2ecf20Sopenharmony_ci .ops = &clk_branch_ops, 4758c2ecf20Sopenharmony_ci .flags = CLK_SET_RATE_PARENT, 4768c2ecf20Sopenharmony_ci }, 4778c2ecf20Sopenharmony_ci }, 4788c2ecf20Sopenharmony_ci}; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_cistatic struct clk_regmap *lcc_mdm9615_clks[] = { 4818c2ecf20Sopenharmony_ci [PLL4] = &pll4.clkr, 4828c2ecf20Sopenharmony_ci [MI2S_OSR_SRC] = &mi2s_osr_src.clkr, 4838c2ecf20Sopenharmony_ci [MI2S_OSR_CLK] = &mi2s_osr_clk.clkr, 4848c2ecf20Sopenharmony_ci [MI2S_DIV_CLK] = &mi2s_div_clk.clkr, 4858c2ecf20Sopenharmony_ci [MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr, 4868c2ecf20Sopenharmony_ci [MI2S_BIT_CLK] = &mi2s_bit_clk.clkr, 4878c2ecf20Sopenharmony_ci [PCM_SRC] = &pcm_src.clkr, 4888c2ecf20Sopenharmony_ci [PCM_CLK_OUT] = &pcm_clk_out.clkr, 4898c2ecf20Sopenharmony_ci [PCM_CLK] = &pcm_clk.clkr, 4908c2ecf20Sopenharmony_ci [SLIMBUS_SRC] = &slimbus_src.clkr, 4918c2ecf20Sopenharmony_ci [AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr, 4928c2ecf20Sopenharmony_ci [SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr, 4938c2ecf20Sopenharmony_ci [CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr, 4948c2ecf20Sopenharmony_ci [CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr, 4958c2ecf20Sopenharmony_ci [CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr, 4968c2ecf20Sopenharmony_ci [CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr, 4978c2ecf20Sopenharmony_ci [CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr, 4988c2ecf20Sopenharmony_ci [SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr, 4998c2ecf20Sopenharmony_ci [SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr, 5008c2ecf20Sopenharmony_ci [SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr, 5018c2ecf20Sopenharmony_ci [SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr, 5028c2ecf20Sopenharmony_ci [SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr, 5038c2ecf20Sopenharmony_ci [CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr, 5048c2ecf20Sopenharmony_ci [CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr, 5058c2ecf20Sopenharmony_ci [CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr, 5068c2ecf20Sopenharmony_ci [CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr, 5078c2ecf20Sopenharmony_ci [CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr, 5088c2ecf20Sopenharmony_ci [SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr, 5098c2ecf20Sopenharmony_ci [SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr, 5108c2ecf20Sopenharmony_ci [SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr, 5118c2ecf20Sopenharmony_ci [SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr, 5128c2ecf20Sopenharmony_ci [SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr, 5138c2ecf20Sopenharmony_ci}; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic const struct regmap_config lcc_mdm9615_regmap_config = { 5168c2ecf20Sopenharmony_ci .reg_bits = 32, 5178c2ecf20Sopenharmony_ci .reg_stride = 4, 5188c2ecf20Sopenharmony_ci .val_bits = 32, 5198c2ecf20Sopenharmony_ci .max_register = 0xfc, 5208c2ecf20Sopenharmony_ci .fast_io = true, 5218c2ecf20Sopenharmony_ci}; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_cistatic const struct qcom_cc_desc lcc_mdm9615_desc = { 5248c2ecf20Sopenharmony_ci .config = &lcc_mdm9615_regmap_config, 5258c2ecf20Sopenharmony_ci .clks = lcc_mdm9615_clks, 5268c2ecf20Sopenharmony_ci .num_clks = ARRAY_SIZE(lcc_mdm9615_clks), 5278c2ecf20Sopenharmony_ci}; 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic const struct of_device_id lcc_mdm9615_match_table[] = { 5308c2ecf20Sopenharmony_ci { .compatible = "qcom,lcc-mdm9615" }, 5318c2ecf20Sopenharmony_ci { } 5328c2ecf20Sopenharmony_ci}; 5338c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, lcc_mdm9615_match_table); 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_cistatic int lcc_mdm9615_probe(struct platform_device *pdev) 5368c2ecf20Sopenharmony_ci{ 5378c2ecf20Sopenharmony_ci u32 val; 5388c2ecf20Sopenharmony_ci struct regmap *regmap; 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci regmap = qcom_cc_map(pdev, &lcc_mdm9615_desc); 5418c2ecf20Sopenharmony_ci if (IS_ERR(regmap)) 5428c2ecf20Sopenharmony_ci return PTR_ERR(regmap); 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci /* Use the correct frequency plan depending on speed of PLL4 */ 5458c2ecf20Sopenharmony_ci regmap_read(regmap, 0x4, &val); 5468c2ecf20Sopenharmony_ci if (val == 0x12) { 5478c2ecf20Sopenharmony_ci slimbus_src.freq_tbl = clk_tbl_aif_osr_492; 5488c2ecf20Sopenharmony_ci mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492; 5498c2ecf20Sopenharmony_ci codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; 5508c2ecf20Sopenharmony_ci spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492; 5518c2ecf20Sopenharmony_ci codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; 5528c2ecf20Sopenharmony_ci spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492; 5538c2ecf20Sopenharmony_ci pcm_src.freq_tbl = clk_tbl_pcm_492; 5548c2ecf20Sopenharmony_ci } 5558c2ecf20Sopenharmony_ci /* Enable PLL4 source on the LPASS Primary PLL Mux */ 5568c2ecf20Sopenharmony_ci regmap_write(regmap, 0xc4, 0x1); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci return qcom_cc_really_probe(pdev, &lcc_mdm9615_desc, regmap); 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic struct platform_driver lcc_mdm9615_driver = { 5628c2ecf20Sopenharmony_ci .probe = lcc_mdm9615_probe, 5638c2ecf20Sopenharmony_ci .driver = { 5648c2ecf20Sopenharmony_ci .name = "lcc-mdm9615", 5658c2ecf20Sopenharmony_ci .of_match_table = lcc_mdm9615_match_table, 5668c2ecf20Sopenharmony_ci }, 5678c2ecf20Sopenharmony_ci}; 5688c2ecf20Sopenharmony_cimodule_platform_driver(lcc_mdm9615_driver); 5698c2ecf20Sopenharmony_ci 5708c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("QCOM LCC MDM9615 Driver"); 5718c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 5728c2ecf20Sopenharmony_ciMODULE_ALIAS("platform:lcc-mdm9615"); 573