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