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/clk-provider.h>
13#include <linux/regmap.h>
14
15#include <dt-bindings/clock/qcom,lcc-ipq806x.h>
16
17#include "common.h"
18#include "clk-regmap.h"
19#include "clk-pll.h"
20#include "clk-rcg.h"
21#include "clk-branch.h"
22#include "clk-regmap-divider.h"
23#include "clk-regmap-mux.h"
24#include "reset.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_data = &(const struct clk_parent_data) {
37			.fw_name = "pxo", .name = "pxo_board",
38		},
39		.num_parents = 1,
40		.ops = &clk_pll_ops,
41	},
42};
43
44static const struct pll_config pll4_config = {
45	.l = 0xf,
46	.m = 0x91,
47	.n = 0xc7,
48	.vco_val = 0x0,
49	.vco_mask = BIT(17) | BIT(16),
50	.pre_div_val = 0x0,
51	.pre_div_mask = BIT(19),
52	.post_div_val = 0x0,
53	.post_div_mask = BIT(21) | BIT(20),
54	.mn_ena_mask = BIT(22),
55	.main_output_mask = BIT(23),
56};
57
58enum {
59	P_PXO,
60	P_PLL4,
61};
62
63static const struct parent_map lcc_pxo_pll4_map[] = {
64	{ P_PXO, 0 },
65	{ P_PLL4, 2 }
66};
67
68static const struct clk_parent_data lcc_pxo_pll4[] = {
69	{ .fw_name = "pxo", .name = "pxo_board" },
70	{ .fw_name = "pll4_vote", .name = "pll4_vote" },
71};
72
73static struct freq_tbl clk_tbl_aif_mi2s[] = {
74	{  1024000, P_PLL4, 4,  1,  96 },
75	{  1411200, P_PLL4, 4,  2, 139 },
76	{  1536000, P_PLL4, 4,  1,  64 },
77	{  2048000, P_PLL4, 4,  1,  48 },
78	{  2116800, P_PLL4, 4,  2,  93 },
79	{  2304000, P_PLL4, 4,  2,  85 },
80	{  2822400, P_PLL4, 4,  6, 209 },
81	{  3072000, P_PLL4, 4,  1,  32 },
82	{  3175200, P_PLL4, 4,  1,  31 },
83	{  4096000, P_PLL4, 4,  1,  24 },
84	{  4233600, P_PLL4, 4,  9, 209 },
85	{  4608000, P_PLL4, 4,  3,  64 },
86	{  5644800, P_PLL4, 4, 12, 209 },
87	{  6144000, P_PLL4, 4,  1,  16 },
88	{  6350400, P_PLL4, 4,  2,  31 },
89	{  8192000, P_PLL4, 4,  1,  12 },
90	{  8467200, P_PLL4, 4, 18, 209 },
91	{  9216000, P_PLL4, 4,  3,  32 },
92	{ 11289600, P_PLL4, 4, 24, 209 },
93	{ 12288000, P_PLL4, 4,  1,   8 },
94	{ 12700800, P_PLL4, 4, 27, 209 },
95	{ 13824000, P_PLL4, 4,  9,  64 },
96	{ 16384000, P_PLL4, 4,  1,   6 },
97	{ 16934400, P_PLL4, 4, 41, 238 },
98	{ 18432000, P_PLL4, 4,  3,  16 },
99	{ 22579200, P_PLL4, 2, 24, 209 },
100	{ 24576000, P_PLL4, 4,  1,   4 },
101	{ 27648000, P_PLL4, 4,  9,  32 },
102	{ 33868800, P_PLL4, 4, 41, 119 },
103	{ 36864000, P_PLL4, 4,  3,   8 },
104	{ 45158400, P_PLL4, 1, 24, 209 },
105	{ 49152000, P_PLL4, 4,  1,   2 },
106	{ 50803200, P_PLL4, 1, 27, 209 },
107	{ }
108};
109
110static struct clk_rcg mi2s_osr_src = {
111	.ns_reg = 0x48,
112	.md_reg = 0x4c,
113	.mn = {
114		.mnctr_en_bit = 8,
115		.mnctr_reset_bit = 7,
116		.mnctr_mode_shift = 5,
117		.n_val_shift = 24,
118		.m_val_shift = 8,
119		.width = 8,
120	},
121	.p = {
122		.pre_div_shift = 3,
123		.pre_div_width = 2,
124	},
125	.s = {
126		.src_sel_shift = 0,
127		.parent_map = lcc_pxo_pll4_map,
128	},
129	.freq_tbl = clk_tbl_aif_mi2s,
130	.clkr = {
131		.enable_reg = 0x48,
132		.enable_mask = BIT(9),
133		.hw.init = &(struct clk_init_data){
134			.name = "mi2s_osr_src",
135			.parent_data = lcc_pxo_pll4,
136			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
137			.ops = &clk_rcg_ops,
138			.flags = CLK_SET_RATE_GATE,
139		},
140	},
141};
142
143static struct clk_branch mi2s_osr_clk = {
144	.halt_reg = 0x50,
145	.halt_bit = 1,
146	.halt_check = BRANCH_HALT_ENABLE,
147	.clkr = {
148		.enable_reg = 0x48,
149		.enable_mask = BIT(17),
150		.hw.init = &(struct clk_init_data){
151			.name = "mi2s_osr_clk",
152			.parent_hws = (const struct clk_hw*[]) {
153				&mi2s_osr_src.clkr.hw,
154			},
155			.num_parents = 1,
156			.ops = &clk_branch_ops,
157			.flags = CLK_SET_RATE_PARENT,
158		},
159	},
160};
161
162static struct clk_regmap_div mi2s_div_clk = {
163	.reg = 0x48,
164	.shift = 10,
165	.width = 4,
166	.clkr = {
167		.hw.init = &(struct clk_init_data){
168			.name = "mi2s_div_clk",
169			.parent_hws = (const struct clk_hw*[]) {
170				&mi2s_osr_src.clkr.hw,
171			},
172			.num_parents = 1,
173			.ops = &clk_regmap_div_ops,
174		},
175	},
176};
177
178static struct clk_branch mi2s_bit_div_clk = {
179	.halt_reg = 0x50,
180	.halt_bit = 0,
181	.halt_check = BRANCH_HALT_ENABLE,
182	.clkr = {
183		.enable_reg = 0x48,
184		.enable_mask = BIT(15),
185		.hw.init = &(struct clk_init_data){
186			.name = "mi2s_bit_div_clk",
187			.parent_hws = (const struct clk_hw*[]) {
188				&mi2s_div_clk.clkr.hw,
189			},
190			.num_parents = 1,
191			.ops = &clk_branch_ops,
192			.flags = CLK_SET_RATE_PARENT,
193		},
194	},
195};
196
197static const struct clk_parent_data lcc_mi2s_bit_div_codec_clk[] = {
198	{ .hw = &mi2s_bit_div_clk.clkr.hw, },
199	{ .fw_name = "mi2s_codec", .name = "mi2s_codec_clk" },
200};
201
202static struct clk_regmap_mux mi2s_bit_clk = {
203	.reg = 0x48,
204	.shift = 14,
205	.width = 1,
206	.clkr = {
207		.hw.init = &(struct clk_init_data){
208			.name = "mi2s_bit_clk",
209			.parent_data = lcc_mi2s_bit_div_codec_clk,
210			.num_parents = ARRAY_SIZE(lcc_mi2s_bit_div_codec_clk),
211			.ops = &clk_regmap_mux_closest_ops,
212			.flags = CLK_SET_RATE_PARENT,
213		},
214	},
215};
216
217static struct freq_tbl clk_tbl_pcm[] = {
218	{   64000, P_PLL4, 4, 1, 1536 },
219	{  128000, P_PLL4, 4, 1,  768 },
220	{  256000, P_PLL4, 4, 1,  384 },
221	{  512000, P_PLL4, 4, 1,  192 },
222	{ 1024000, P_PLL4, 4, 1,   96 },
223	{ 2048000, P_PLL4, 4, 1,   48 },
224	{ },
225};
226
227static struct clk_rcg pcm_src = {
228	.ns_reg = 0x54,
229	.md_reg = 0x58,
230	.mn = {
231		.mnctr_en_bit = 8,
232		.mnctr_reset_bit = 7,
233		.mnctr_mode_shift = 5,
234		.n_val_shift = 16,
235		.m_val_shift = 16,
236		.width = 16,
237	},
238	.p = {
239		.pre_div_shift = 3,
240		.pre_div_width = 2,
241	},
242	.s = {
243		.src_sel_shift = 0,
244		.parent_map = lcc_pxo_pll4_map,
245	},
246	.freq_tbl = clk_tbl_pcm,
247	.clkr = {
248		.enable_reg = 0x54,
249		.enable_mask = BIT(9),
250		.hw.init = &(struct clk_init_data){
251			.name = "pcm_src",
252			.parent_data = lcc_pxo_pll4,
253			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
254			.ops = &clk_rcg_ops,
255			.flags = CLK_SET_RATE_GATE,
256		},
257	},
258};
259
260static struct clk_branch pcm_clk_out = {
261	.halt_reg = 0x5c,
262	.halt_bit = 0,
263	.halt_check = BRANCH_HALT_ENABLE,
264	.clkr = {
265		.enable_reg = 0x54,
266		.enable_mask = BIT(11),
267		.hw.init = &(struct clk_init_data){
268			.name = "pcm_clk_out",
269			.parent_hws = (const struct clk_hw*[]) {
270				&pcm_src.clkr.hw,
271			},
272			.num_parents = 1,
273			.ops = &clk_branch_ops,
274			.flags = CLK_SET_RATE_PARENT,
275		},
276	},
277};
278
279static const struct clk_parent_data lcc_pcm_clk_out_codec_clk[] = {
280	{ .hw = &pcm_clk_out.clkr.hw, },
281	{ .fw_name = "pcm_codec_clk", .name = "pcm_codec_clk" },
282};
283
284static struct clk_regmap_mux pcm_clk = {
285	.reg = 0x54,
286	.shift = 10,
287	.width = 1,
288	.clkr = {
289		.hw.init = &(struct clk_init_data){
290			.name = "pcm_clk",
291			.parent_data = lcc_pcm_clk_out_codec_clk,
292			.num_parents = ARRAY_SIZE(lcc_pcm_clk_out_codec_clk),
293			.ops = &clk_regmap_mux_closest_ops,
294			.flags = CLK_SET_RATE_PARENT,
295		},
296	},
297};
298
299static struct freq_tbl clk_tbl_aif_osr[] = {
300	{  2822400, P_PLL4, 1, 147, 20480 },
301	{  4096000, P_PLL4, 1,   1,    96 },
302	{  5644800, P_PLL4, 1, 147, 10240 },
303	{  6144000, P_PLL4, 1,   1,    64 },
304	{ 11289600, P_PLL4, 1, 147,  5120 },
305	{ 12288000, P_PLL4, 1,   1,    32 },
306	{ 22579200, P_PLL4, 1, 147,  2560 },
307	{ 24576000, P_PLL4, 1,   1,    16 },
308	{ },
309};
310
311static struct clk_rcg spdif_src = {
312	.ns_reg = 0xcc,
313	.md_reg = 0xd0,
314	.mn = {
315		.mnctr_en_bit = 8,
316		.mnctr_reset_bit = 7,
317		.mnctr_mode_shift = 5,
318		.n_val_shift = 16,
319		.m_val_shift = 16,
320		.width = 8,
321	},
322	.p = {
323		.pre_div_shift = 3,
324		.pre_div_width = 2,
325	},
326	.s = {
327		.src_sel_shift = 0,
328		.parent_map = lcc_pxo_pll4_map,
329	},
330	.freq_tbl = clk_tbl_aif_osr,
331	.clkr = {
332		.enable_reg = 0xcc,
333		.enable_mask = BIT(9),
334		.hw.init = &(struct clk_init_data){
335			.name = "spdif_src",
336			.parent_data = lcc_pxo_pll4,
337			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
338			.ops = &clk_rcg_ops,
339			.flags = CLK_SET_RATE_GATE,
340		},
341	},
342};
343
344static struct clk_branch spdif_clk = {
345	.halt_reg = 0xd4,
346	.halt_bit = 1,
347	.halt_check = BRANCH_HALT_ENABLE,
348	.clkr = {
349		.enable_reg = 0xcc,
350		.enable_mask = BIT(12),
351		.hw.init = &(struct clk_init_data){
352			.name = "spdif_clk",
353			.parent_hws = (const struct clk_hw*[]) {
354				&spdif_src.clkr.hw,
355			},
356			.num_parents = 1,
357			.ops = &clk_branch_ops,
358			.flags = CLK_SET_RATE_PARENT,
359		},
360	},
361};
362
363static struct freq_tbl clk_tbl_ahbix[] = {
364	{ 131072000, P_PLL4, 1, 1, 3 },
365	{ },
366};
367
368static struct clk_rcg ahbix_clk = {
369	.ns_reg = 0x38,
370	.md_reg = 0x3c,
371	.mn = {
372		.mnctr_en_bit = 8,
373		.mnctr_reset_bit = 7,
374		.mnctr_mode_shift = 5,
375		.n_val_shift = 24,
376		.m_val_shift = 8,
377		.width = 8,
378	},
379	.p = {
380		.pre_div_shift = 3,
381		.pre_div_width = 2,
382	},
383	.s = {
384		.src_sel_shift = 0,
385		.parent_map = lcc_pxo_pll4_map,
386	},
387	.freq_tbl = clk_tbl_ahbix,
388	.clkr = {
389		.enable_reg = 0x38,
390		.enable_mask = BIT(11),
391		.hw.init = &(struct clk_init_data){
392			.name = "ahbix",
393			.parent_data = lcc_pxo_pll4,
394			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),
395			.ops = &clk_rcg_lcc_ops,
396		},
397	},
398};
399
400static struct clk_regmap *lcc_ipq806x_clks[] = {
401	[PLL4] = &pll4.clkr,
402	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,
403	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,
404	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,
405	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,
406	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,
407	[PCM_SRC] = &pcm_src.clkr,
408	[PCM_CLK_OUT] = &pcm_clk_out.clkr,
409	[PCM_CLK] = &pcm_clk.clkr,
410	[SPDIF_SRC] = &spdif_src.clkr,
411	[SPDIF_CLK] = &spdif_clk.clkr,
412	[AHBIX_CLK] = &ahbix_clk.clkr,
413};
414
415static const struct qcom_reset_map lcc_ipq806x_resets[] = {
416	[LCC_PCM_RESET] = { 0x54, 13 },
417};
418
419static const struct regmap_config lcc_ipq806x_regmap_config = {
420	.reg_bits	= 32,
421	.reg_stride	= 4,
422	.val_bits	= 32,
423	.max_register	= 0xfc,
424	.fast_io	= true,
425};
426
427static const struct qcom_cc_desc lcc_ipq806x_desc = {
428	.config = &lcc_ipq806x_regmap_config,
429	.clks = lcc_ipq806x_clks,
430	.num_clks = ARRAY_SIZE(lcc_ipq806x_clks),
431	.resets = lcc_ipq806x_resets,
432	.num_resets = ARRAY_SIZE(lcc_ipq806x_resets),
433};
434
435static const struct of_device_id lcc_ipq806x_match_table[] = {
436	{ .compatible = "qcom,lcc-ipq8064" },
437	{ }
438};
439MODULE_DEVICE_TABLE(of, lcc_ipq806x_match_table);
440
441static int lcc_ipq806x_probe(struct platform_device *pdev)
442{
443	u32 val;
444	struct regmap *regmap;
445
446	regmap = qcom_cc_map(pdev, &lcc_ipq806x_desc);
447	if (IS_ERR(regmap))
448		return PTR_ERR(regmap);
449
450	/* Configure the rate of PLL4 if the bootloader hasn't already */
451	regmap_read(regmap, 0x0, &val);
452	if (!val)
453		clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);
454	/* Enable PLL4 source on the LPASS Primary PLL Mux */
455	regmap_write(regmap, 0xc4, 0x1);
456
457	return qcom_cc_really_probe(pdev, &lcc_ipq806x_desc, regmap);
458}
459
460static struct platform_driver lcc_ipq806x_driver = {
461	.probe		= lcc_ipq806x_probe,
462	.driver		= {
463		.name	= "lcc-ipq806x",
464		.of_match_table = lcc_ipq806x_match_table,
465	},
466};
467module_platform_driver(lcc_ipq806x_driver);
468
469MODULE_DESCRIPTION("QCOM LCC IPQ806x Driver");
470MODULE_LICENSE("GPL v2");
471MODULE_ALIAS("platform:lcc-ipq806x");
472