1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2014, The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/kernel.h>
7#include <linux/bitops.h>
8#include <linux/err.h>
9#include <linux/platform_device.h>
10#include <linux/module.h>
11#include <linux/of.h>
12#include <linux/of_device.h>
13#include <linux/clk-provider.h>
14#include <linux/regmap.h>
15
16#include <dt-bindings/clock/qcom,lcc-msm8960.h>
17
18#include "common.h"
19#include "clk-regmap.h"
20#include "clk-pll.h"
21#include "clk-rcg.h"
22#include "clk-branch.h"
23#include "clk-regmap-divider.h"
24#include "clk-regmap-mux.h"
25
26static struct clk_pll pll4 = {
27	.l_reg = 0x4,
28	.m_reg = 0x8,
29	.n_reg = 0xc,
30	.config_reg = 0x14,
31	.mode_reg = 0x0,
32	.status_reg = 0x18,
33	.status_bit = 16,
34	.clkr.hw.init = &(struct clk_init_data){
35		.name = "pll4",
36		.parent_names = (const char *[]){ "pxo" },
37		.num_parents = 1,
38		.ops = &clk_pll_ops,
39	},
40};
41
42enum {
43	P_PXO,
44	P_PLL4,
45};
46
47static const struct parent_map lcc_pxo_pll4_map[] = {
48	{ P_PXO, 0 },
49	{ P_PLL4, 2 }
50};
51
52static const char * const lcc_pxo_pll4[] = {
53	"pxo",
54	"pll4_vote",
55};
56
57static struct freq_tbl clk_tbl_aif_osr_492[] = {
58	{   512000, P_PLL4, 4, 1, 240 },
59	{   768000, P_PLL4, 4, 1, 160 },
60	{  1024000, P_PLL4, 4, 1, 120 },
61	{  1536000, P_PLL4, 4, 1,  80 },
62	{  2048000, P_PLL4, 4, 1,  60 },
63	{  3072000, P_PLL4, 4, 1,  40 },
64	{  4096000, P_PLL4, 4, 1,  30 },
65	{  6144000, P_PLL4, 4, 1,  20 },
66	{  8192000, P_PLL4, 4, 1,  15 },
67	{ 12288000, P_PLL4, 4, 1,  10 },
68	{ 24576000, P_PLL4, 4, 1,   5 },
69	{ 27000000, P_PXO,  1, 0,   0 },
70	{ }
71};
72
73static struct freq_tbl clk_tbl_aif_osr_393[] = {
74	{   512000, P_PLL4, 4, 1, 192 },
75	{   768000, P_PLL4, 4, 1, 128 },
76	{  1024000, P_PLL4, 4, 1,  96 },
77	{  1536000, P_PLL4, 4, 1,  64 },
78	{  2048000, P_PLL4, 4, 1,  48 },
79	{  3072000, P_PLL4, 4, 1,  32 },
80	{  4096000, P_PLL4, 4, 1,  24 },
81	{  6144000, P_PLL4, 4, 1,  16 },
82	{  8192000, P_PLL4, 4, 1,  12 },
83	{ 12288000, P_PLL4, 4, 1,   8 },
84	{ 24576000, P_PLL4, 4, 1,   4 },
85	{ 27000000, P_PXO,  1, 0,   0 },
86	{ }
87};
88
89static struct clk_rcg mi2s_osr_src = {
90	.ns_reg = 0x48,
91	.md_reg = 0x4c,
92	.mn = {
93		.mnctr_en_bit = 8,
94		.mnctr_reset_bit = 7,
95		.mnctr_mode_shift = 5,
96		.n_val_shift = 24,
97		.m_val_shift = 8,
98		.width = 8,
99	},
100	.p = {
101		.pre_div_shift = 3,
102		.pre_div_width = 2,
103	},
104	.s = {
105		.src_sel_shift = 0,
106		.parent_map = lcc_pxo_pll4_map,
107	},
108	.freq_tbl = clk_tbl_aif_osr_393,
109	.clkr = {
110		.enable_reg = 0x48,
111		.enable_mask = BIT(9),
112		.hw.init = &(struct clk_init_data){
113			.name = "mi2s_osr_src",
114			.parent_names = lcc_pxo_pll4,
115			.num_parents = 2,
116			.ops = &clk_rcg_ops,
117			.flags = CLK_SET_RATE_GATE,
118		},
119	},
120};
121
122static const char * const lcc_mi2s_parents[] = {
123	"mi2s_osr_src",
124};
125
126static struct clk_branch mi2s_osr_clk = {
127	.halt_reg = 0x50,
128	.halt_bit = 1,
129	.halt_check = BRANCH_HALT_ENABLE,
130	.clkr = {
131		.enable_reg = 0x48,
132		.enable_mask = BIT(17),
133		.hw.init = &(struct clk_init_data){
134			.name = "mi2s_osr_clk",
135			.parent_names = lcc_mi2s_parents,
136			.num_parents = 1,
137			.ops = &clk_branch_ops,
138			.flags = CLK_SET_RATE_PARENT,
139		},
140	},
141};
142
143static struct clk_regmap_div mi2s_div_clk = {
144	.reg = 0x48,
145	.shift = 10,
146	.width = 4,
147	.clkr = {
148		.enable_reg = 0x48,
149		.enable_mask = BIT(15),
150		.hw.init = &(struct clk_init_data){
151			.name = "mi2s_div_clk",
152			.parent_names = lcc_mi2s_parents,
153			.num_parents = 1,
154			.ops = &clk_regmap_div_ops,
155		},
156	},
157};
158
159static struct clk_branch mi2s_bit_div_clk = {
160	.halt_reg = 0x50,
161	.halt_bit = 0,
162	.halt_check = BRANCH_HALT_ENABLE,
163	.clkr = {
164		.enable_reg = 0x48,
165		.enable_mask = BIT(15),
166		.hw.init = &(struct clk_init_data){
167			.name = "mi2s_bit_div_clk",
168			.parent_names = (const char *[]){ "mi2s_div_clk" },
169			.num_parents = 1,
170			.ops = &clk_branch_ops,
171			.flags = CLK_SET_RATE_PARENT,
172		},
173	},
174};
175
176static struct clk_regmap_mux mi2s_bit_clk = {
177	.reg = 0x48,
178	.shift = 14,
179	.width = 1,
180	.clkr = {
181		.hw.init = &(struct clk_init_data){
182			.name = "mi2s_bit_clk",
183			.parent_names = (const char *[]){
184				"mi2s_bit_div_clk",
185				"mi2s_codec_clk",
186			},
187			.num_parents = 2,
188			.ops = &clk_regmap_mux_closest_ops,
189			.flags = CLK_SET_RATE_PARENT,
190		},
191	},
192};
193
194#define CLK_AIF_OSR_DIV(prefix, _ns, _md, hr)			\
195static struct clk_rcg prefix##_osr_src = {			\
196	.ns_reg = _ns,						\
197	.md_reg = _md,						\
198	.mn = {							\
199		.mnctr_en_bit = 8,				\
200		.mnctr_reset_bit = 7,				\
201		.mnctr_mode_shift = 5,				\
202		.n_val_shift = 24,				\
203		.m_val_shift = 8,				\
204		.width = 8,					\
205	},							\
206	.p = {							\
207		.pre_div_shift = 3,				\
208		.pre_div_width = 2,				\
209	},							\
210	.s = {							\
211		.src_sel_shift = 0,				\
212		.parent_map = lcc_pxo_pll4_map,			\
213	},							\
214	.freq_tbl = clk_tbl_aif_osr_393,			\
215	.clkr = {						\
216		.enable_reg = _ns,				\
217		.enable_mask = BIT(9),				\
218		.hw.init = &(struct clk_init_data){		\
219			.name = #prefix "_osr_src",		\
220			.parent_names = lcc_pxo_pll4,		\
221			.num_parents = 2,			\
222			.ops = &clk_rcg_ops,			\
223			.flags = CLK_SET_RATE_GATE,		\
224		},						\
225	},							\
226};								\
227								\
228static const char * const lcc_##prefix##_parents[] = {		\
229	#prefix "_osr_src",					\
230};								\
231								\
232static struct clk_branch prefix##_osr_clk = {			\
233	.halt_reg = hr,						\
234	.halt_bit = 1,						\
235	.halt_check = BRANCH_HALT_ENABLE,			\
236	.clkr = {						\
237		.enable_reg = _ns,				\
238		.enable_mask = BIT(21),				\
239		.hw.init = &(struct clk_init_data){		\
240			.name = #prefix "_osr_clk",		\
241			.parent_names = lcc_##prefix##_parents,	\
242			.num_parents = 1,			\
243			.ops = &clk_branch_ops,			\
244			.flags = CLK_SET_RATE_PARENT,		\
245		},						\
246	},							\
247};								\
248								\
249static struct clk_regmap_div prefix##_div_clk = {		\
250	.reg = _ns,						\
251	.shift = 10,						\
252	.width = 8,						\
253	.clkr = {						\
254		.hw.init = &(struct clk_init_data){		\
255			.name = #prefix "_div_clk",		\
256			.parent_names = lcc_##prefix##_parents,	\
257			.num_parents = 1,			\
258			.ops = &clk_regmap_div_ops,		\
259		},						\
260	},							\
261};								\
262								\
263static struct clk_branch prefix##_bit_div_clk = {		\
264	.halt_reg = hr,						\
265	.halt_bit = 0,						\
266	.halt_check = BRANCH_HALT_ENABLE,			\
267	.clkr = {						\
268		.enable_reg = _ns,				\
269		.enable_mask = BIT(19),				\
270		.hw.init = &(struct clk_init_data){		\
271			.name = #prefix "_bit_div_clk",		\
272			.parent_names = (const char *[]){	\
273				#prefix "_div_clk"		\
274			}, 					\
275			.num_parents = 1,			\
276			.ops = &clk_branch_ops,			\
277			.flags = CLK_SET_RATE_PARENT,		\
278		},						\
279	},							\
280};								\
281								\
282static struct clk_regmap_mux prefix##_bit_clk = {		\
283	.reg = _ns,						\
284	.shift = 18,						\
285	.width = 1,						\
286	.clkr = {						\
287		.hw.init = &(struct clk_init_data){		\
288			.name = #prefix "_bit_clk",		\
289			.parent_names = (const char *[]){	\
290				#prefix "_bit_div_clk",		\
291				#prefix "_codec_clk",		\
292			},					\
293			.num_parents = 2,			\
294			.ops = &clk_regmap_mux_closest_ops,	\
295			.flags = CLK_SET_RATE_PARENT,		\
296		},						\
297	},							\
298}
299
300CLK_AIF_OSR_DIV(codec_i2s_mic, 0x60, 0x64, 0x68);
301CLK_AIF_OSR_DIV(spare_i2s_mic, 0x78, 0x7c, 0x80);
302CLK_AIF_OSR_DIV(codec_i2s_spkr, 0x6c, 0x70, 0x74);
303CLK_AIF_OSR_DIV(spare_i2s_spkr, 0x84, 0x88, 0x8c);
304
305static struct freq_tbl clk_tbl_pcm_492[] = {
306	{   256000, P_PLL4, 4, 1, 480 },
307	{   512000, P_PLL4, 4, 1, 240 },
308	{   768000, P_PLL4, 4, 1, 160 },
309	{  1024000, P_PLL4, 4, 1, 120 },
310	{  1536000, P_PLL4, 4, 1,  80 },
311	{  2048000, P_PLL4, 4, 1,  60 },
312	{  3072000, P_PLL4, 4, 1,  40 },
313	{  4096000, P_PLL4, 4, 1,  30 },
314	{  6144000, P_PLL4, 4, 1,  20 },
315	{  8192000, P_PLL4, 4, 1,  15 },
316	{ 12288000, P_PLL4, 4, 1,  10 },
317	{ 24576000, P_PLL4, 4, 1,   5 },
318	{ 27000000, P_PXO,  1, 0,   0 },
319	{ }
320};
321
322static struct freq_tbl clk_tbl_pcm_393[] = {
323	{   256000, P_PLL4, 4, 1, 384 },
324	{   512000, P_PLL4, 4, 1, 192 },
325	{   768000, P_PLL4, 4, 1, 128 },
326	{  1024000, P_PLL4, 4, 1,  96 },
327	{  1536000, P_PLL4, 4, 1,  64 },
328	{  2048000, P_PLL4, 4, 1,  48 },
329	{  3072000, P_PLL4, 4, 1,  32 },
330	{  4096000, P_PLL4, 4, 1,  24 },
331	{  6144000, P_PLL4, 4, 1,  16 },
332	{  8192000, P_PLL4, 4, 1,  12 },
333	{ 12288000, P_PLL4, 4, 1,   8 },
334	{ 24576000, P_PLL4, 4, 1,   4 },
335	{ 27000000, P_PXO,  1, 0,   0 },
336	{ }
337};
338
339static struct clk_rcg pcm_src = {
340	.ns_reg = 0x54,
341	.md_reg = 0x58,
342	.mn = {
343		.mnctr_en_bit = 8,
344		.mnctr_reset_bit = 7,
345		.mnctr_mode_shift = 5,
346		.n_val_shift = 16,
347		.m_val_shift = 16,
348		.width = 16,
349	},
350	.p = {
351		.pre_div_shift = 3,
352		.pre_div_width = 2,
353	},
354	.s = {
355		.src_sel_shift = 0,
356		.parent_map = lcc_pxo_pll4_map,
357	},
358	.freq_tbl = clk_tbl_pcm_393,
359	.clkr = {
360		.enable_reg = 0x54,
361		.enable_mask = BIT(9),
362		.hw.init = &(struct clk_init_data){
363			.name = "pcm_src",
364			.parent_names = lcc_pxo_pll4,
365			.num_parents = 2,
366			.ops = &clk_rcg_ops,
367			.flags = CLK_SET_RATE_GATE,
368		},
369	},
370};
371
372static struct clk_branch pcm_clk_out = {
373	.halt_reg = 0x5c,
374	.halt_bit = 0,
375	.halt_check = BRANCH_HALT_ENABLE,
376	.clkr = {
377		.enable_reg = 0x54,
378		.enable_mask = BIT(11),
379		.hw.init = &(struct clk_init_data){
380			.name = "pcm_clk_out",
381			.parent_names = (const char *[]){ "pcm_src" },
382			.num_parents = 1,
383			.ops = &clk_branch_ops,
384			.flags = CLK_SET_RATE_PARENT,
385		},
386	},
387};
388
389static struct clk_regmap_mux pcm_clk = {
390	.reg = 0x54,
391	.shift = 10,
392	.width = 1,
393	.clkr = {
394		.hw.init = &(struct clk_init_data){
395			.name = "pcm_clk",
396			.parent_names = (const char *[]){
397				"pcm_clk_out",
398				"pcm_codec_clk",
399			},
400			.num_parents = 2,
401			.ops = &clk_regmap_mux_closest_ops,
402			.flags = CLK_SET_RATE_PARENT,
403		},
404	},
405};
406
407static struct clk_rcg slimbus_src = {
408	.ns_reg = 0xcc,
409	.md_reg = 0xd0,
410	.mn = {
411		.mnctr_en_bit = 8,
412		.mnctr_reset_bit = 7,
413		.mnctr_mode_shift = 5,
414		.n_val_shift = 24,
415		.m_val_shift = 8,
416		.width = 8,
417	},
418	.p = {
419		.pre_div_shift = 3,
420		.pre_div_width = 2,
421	},
422	.s = {
423		.src_sel_shift = 0,
424		.parent_map = lcc_pxo_pll4_map,
425	},
426	.freq_tbl = clk_tbl_aif_osr_393,
427	.clkr = {
428		.enable_reg = 0xcc,
429		.enable_mask = BIT(9),
430		.hw.init = &(struct clk_init_data){
431			.name = "slimbus_src",
432			.parent_names = lcc_pxo_pll4,
433			.num_parents = 2,
434			.ops = &clk_rcg_ops,
435			.flags = CLK_SET_RATE_GATE,
436		},
437	},
438};
439
440static const char * const lcc_slimbus_parents[] = {
441	"slimbus_src",
442};
443
444static struct clk_branch audio_slimbus_clk = {
445	.halt_reg = 0xd4,
446	.halt_bit = 0,
447	.halt_check = BRANCH_HALT_ENABLE,
448	.clkr = {
449		.enable_reg = 0xcc,
450		.enable_mask = BIT(10),
451		.hw.init = &(struct clk_init_data){
452			.name = "audio_slimbus_clk",
453			.parent_names = lcc_slimbus_parents,
454			.num_parents = 1,
455			.ops = &clk_branch_ops,
456			.flags = CLK_SET_RATE_PARENT,
457		},
458	},
459};
460
461static struct clk_branch sps_slimbus_clk = {
462	.halt_reg = 0xd4,
463	.halt_bit = 1,
464	.halt_check = BRANCH_HALT_ENABLE,
465	.clkr = {
466		.enable_reg = 0xcc,
467		.enable_mask = BIT(12),
468		.hw.init = &(struct clk_init_data){
469			.name = "sps_slimbus_clk",
470			.parent_names = lcc_slimbus_parents,
471			.num_parents = 1,
472			.ops = &clk_branch_ops,
473			.flags = CLK_SET_RATE_PARENT,
474		},
475	},
476};
477
478static struct clk_regmap *lcc_msm8960_clks[] = {
479	[PLL4] = &pll4.clkr,
480	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
481	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
482	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
483	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
484	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
485	[PCM_SRC] = &pcm_src.clkr,
486	[PCM_CLK_OUT] = &pcm_clk_out.clkr,
487	[PCM_CLK] = &pcm_clk.clkr,
488	[SLIMBUS_SRC] = &slimbus_src.clkr,
489	[AUDIO_SLIMBUS_CLK] = &audio_slimbus_clk.clkr,
490	[SPS_SLIMBUS_CLK] = &sps_slimbus_clk.clkr,
491	[CODEC_I2S_MIC_OSR_SRC] = &codec_i2s_mic_osr_src.clkr,
492	[CODEC_I2S_MIC_OSR_CLK] = &codec_i2s_mic_osr_clk.clkr,
493	[CODEC_I2S_MIC_DIV_CLK] = &codec_i2s_mic_div_clk.clkr,
494	[CODEC_I2S_MIC_BIT_DIV_CLK] = &codec_i2s_mic_bit_div_clk.clkr,
495	[CODEC_I2S_MIC_BIT_CLK] = &codec_i2s_mic_bit_clk.clkr,
496	[SPARE_I2S_MIC_OSR_SRC] = &spare_i2s_mic_osr_src.clkr,
497	[SPARE_I2S_MIC_OSR_CLK] = &spare_i2s_mic_osr_clk.clkr,
498	[SPARE_I2S_MIC_DIV_CLK] = &spare_i2s_mic_div_clk.clkr,
499	[SPARE_I2S_MIC_BIT_DIV_CLK] = &spare_i2s_mic_bit_div_clk.clkr,
500	[SPARE_I2S_MIC_BIT_CLK] = &spare_i2s_mic_bit_clk.clkr,
501	[CODEC_I2S_SPKR_OSR_SRC] = &codec_i2s_spkr_osr_src.clkr,
502	[CODEC_I2S_SPKR_OSR_CLK] = &codec_i2s_spkr_osr_clk.clkr,
503	[CODEC_I2S_SPKR_DIV_CLK] = &codec_i2s_spkr_div_clk.clkr,
504	[CODEC_I2S_SPKR_BIT_DIV_CLK] = &codec_i2s_spkr_bit_div_clk.clkr,
505	[CODEC_I2S_SPKR_BIT_CLK] = &codec_i2s_spkr_bit_clk.clkr,
506	[SPARE_I2S_SPKR_OSR_SRC] = &spare_i2s_spkr_osr_src.clkr,
507	[SPARE_I2S_SPKR_OSR_CLK] = &spare_i2s_spkr_osr_clk.clkr,
508	[SPARE_I2S_SPKR_DIV_CLK] = &spare_i2s_spkr_div_clk.clkr,
509	[SPARE_I2S_SPKR_BIT_DIV_CLK] = &spare_i2s_spkr_bit_div_clk.clkr,
510	[SPARE_I2S_SPKR_BIT_CLK] = &spare_i2s_spkr_bit_clk.clkr,
511};
512
513static const struct regmap_config lcc_msm8960_regmap_config = {
514	.reg_bits	= 32,
515	.reg_stride	= 4,
516	.val_bits	= 32,
517	.max_register	= 0xfc,
518	.fast_io	= true,
519};
520
521static const struct qcom_cc_desc lcc_msm8960_desc = {
522	.config = &lcc_msm8960_regmap_config,
523	.clks = lcc_msm8960_clks,
524	.num_clks = ARRAY_SIZE(lcc_msm8960_clks),
525};
526
527static const struct of_device_id lcc_msm8960_match_table[] = {
528	{ .compatible = "qcom,lcc-msm8960" },
529	{ .compatible = "qcom,lcc-apq8064" },
530	{ }
531};
532MODULE_DEVICE_TABLE(of, lcc_msm8960_match_table);
533
534static int lcc_msm8960_probe(struct platform_device *pdev)
535{
536	u32 val;
537	struct regmap *regmap;
538
539	regmap = qcom_cc_map(pdev, &lcc_msm8960_desc);
540	if (IS_ERR(regmap))
541		return PTR_ERR(regmap);
542
543	/* Use the correct frequency plan depending on speed of PLL4 */
544	regmap_read(regmap, 0x4, &val);
545	if (val == 0x12) {
546		slimbus_src.freq_tbl = clk_tbl_aif_osr_492;
547		mi2s_osr_src.freq_tbl = clk_tbl_aif_osr_492;
548		codec_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
549		spare_i2s_mic_osr_src.freq_tbl = clk_tbl_aif_osr_492;
550		codec_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
551		spare_i2s_spkr_osr_src.freq_tbl = clk_tbl_aif_osr_492;
552		pcm_src.freq_tbl = clk_tbl_pcm_492;
553	}
554	/* Enable PLL4 source on the LPASS Primary PLL Mux */
555	regmap_write(regmap, 0xc4, 0x1);
556
557	return qcom_cc_really_probe(pdev, &lcc_msm8960_desc, regmap);
558}
559
560static struct platform_driver lcc_msm8960_driver = {
561	.probe		= lcc_msm8960_probe,
562	.driver		= {
563		.name	= "lcc-msm8960",
564		.of_match_table = lcc_msm8960_match_table,
565	},
566};
567module_platform_driver(lcc_msm8960_driver);
568
569MODULE_DESCRIPTION("QCOM LCC MSM8960 Driver");
570MODULE_LICENSE("GPL v2");
571MODULE_ALIAS("platform:lcc-msm8960");
572