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