File Index
Files and directories
Sign in
FILE

clk-mt6735-topckgen.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/mediatek/clk-mt6735-topckgen.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (c) 2022 Yassine Oudjana <y.oudjana@protonmail.com>
  4 */
  5
  6#include <linux/clk-provider.h>
  7#include <linux/platform_device.h>
  8
  9#include "clk-mtk.h"
 10#include "clk-mux.h"
 11
 12#include <dt-bindings/clock/mediatek,mt6735-topckgen.h>
 13
 14#define CLK_CFG_0		0x40
 15#define CLK_CFG_0_SET		0x44
 16#define CLK_CFG_0_CLR		0x48
 17#define CLK_CFG_1		0x50
 18#define CLK_CFG_1_SET		0x54
 19#define CLK_CFG_1_CLR		0x58
 20#define CLK_CFG_2		0x60
 21#define CLK_CFG_2_SET		0x64
 22#define CLK_CFG_2_CLR		0x68
 23#define CLK_CFG_3		0x70
 24#define CLK_CFG_3_SET		0x74
 25#define CLK_CFG_3_CLR		0x78
 26#define CLK_CFG_4		0x80
 27#define CLK_CFG_4_SET		0x84
 28#define CLK_CFG_4_CLR		0x88
 29#define CLK_CFG_5		0x90
 30#define CLK_CFG_5_SET		0x94
 31#define CLK_CFG_5_CLR		0x98
 32#define CLK_CFG_6		0xa0
 33#define CLK_CFG_6_SET		0xa4
 34#define CLK_CFG_6_CLR		0xa8
 35#define CLK_CFG_7		0xb0
 36#define CLK_CFG_7_SET		0xb4
 37#define CLK_CFG_7_CLR		0xb8
 38
 39static DEFINE_SPINLOCK(mt6735_topckgen_lock);
 40
 41/* Some clocks with unknown details are modeled as fixed clocks */
 42static const struct mtk_fixed_clk topckgen_fixed_clks[] = {
 43	/*
 44	 * This clock is available as a parent option for multiple
 45	 * muxes and seems like an alternative name for clk26m at first,
 46	 * but it appears alongside it in several muxes which should
 47	 * mean it is a separate clock.
 48	 */
 49	FIXED_CLK(CLK_TOP_AD_SYS_26M_CK, "ad_sys_26m_ck", "clk26m", 26 * MHZ),
 50	/*
 51	 * This clock is the parent of DMPLL divisors. It might be MEMPLL
 52	 * or its parent, as DMPLL appears to be an alternative name for
 53	 * MEMPLL.
 54	 */
 55	FIXED_CLK(CLK_TOP_CLKPH_MCK_O, "clkph_mck_o", NULL, 0),
 56	/*
 57	 * DMPLL clock (dmpll_ck), controlled by DDRPHY.
 58	 */
 59	FIXED_CLK(CLK_TOP_DMPLL, "dmpll", "clkph_mck_o", 0),
 60	/*
 61	 * MIPI DPI clock. Parent option for dpi0_sel. Unknown parent.
 62	 */
 63	FIXED_CLK(CLK_TOP_DPI_CK, "dpi_ck", NULL, 0),
 64	/*
 65	 * This clock is a child of WHPLL which is controlled by
 66	 * the modem.
 67	 */
 68	FIXED_CLK(CLK_TOP_WHPLL_AUDIO_CK, "whpll_audio_ck", NULL, 0)
 69};
 70
 71static const struct mtk_fixed_factor topckgen_factors[] = {
 72	FACTOR(CLK_TOP_SYSPLL_D2, "syspll_d2", "mainpll", 1, 2),
 73	FACTOR(CLK_TOP_SYSPLL_D3, "syspll_d3", "mainpll", 1, 3),
 74	FACTOR(CLK_TOP_SYSPLL_D5, "syspll_d5", "mainpll", 1, 5),
 75	FACTOR(CLK_TOP_SYSPLL1_D2, "syspll1_d2", "mainpll", 1, 2),
 76	FACTOR(CLK_TOP_SYSPLL1_D4, "syspll1_d4", "mainpll", 1, 4),
 77	FACTOR(CLK_TOP_SYSPLL1_D8, "syspll1_d8", "mainpll", 1, 8),
 78	FACTOR(CLK_TOP_SYSPLL1_D16, "syspll1_d16", "mainpll", 1, 16),
 79	FACTOR(CLK_TOP_SYSPLL2_D2, "syspll2_d2", "mainpll", 1, 2),
 80	FACTOR(CLK_TOP_SYSPLL2_D4, "syspll2_d4", "mainpll", 1, 4),
 81	FACTOR(CLK_TOP_SYSPLL3_D2, "syspll3_d2", "mainpll", 1, 2),
 82	FACTOR(CLK_TOP_SYSPLL3_D4, "syspll3_d4", "mainpll", 1, 4),
 83	FACTOR(CLK_TOP_SYSPLL4_D2, "syspll4_d2", "mainpll", 1, 2),
 84	FACTOR(CLK_TOP_SYSPLL4_D4, "syspll4_d4", "mainpll", 1, 4),
 85	FACTOR(CLK_TOP_UNIVPLL_D2, "univpll_d2", "univpll", 1, 2),
 86	FACTOR(CLK_TOP_UNIVPLL_D3, "univpll_d3", "univpll", 1, 3),
 87	FACTOR(CLK_TOP_UNIVPLL_D5, "univpll_d5", "univpll", 1, 5),
 88	FACTOR(CLK_TOP_UNIVPLL_D26, "univpll_d26", "univpll", 1, 26),
 89	FACTOR(CLK_TOP_UNIVPLL1_D2, "univpll1_d2", "univpll", 1, 2),
 90	FACTOR(CLK_TOP_UNIVPLL1_D4, "univpll1_d4", "univpll", 1, 4),
 91	FACTOR(CLK_TOP_UNIVPLL1_D8, "univpll1_d8", "univpll", 1, 8),
 92	FACTOR(CLK_TOP_UNIVPLL2_D2, "univpll2_d2", "univpll", 1, 2),
 93	FACTOR(CLK_TOP_UNIVPLL2_D4, "univpll2_d4", "univpll", 1, 4),
 94	FACTOR(CLK_TOP_UNIVPLL2_D8, "univpll2_d8", "univpll", 1, 8),
 95	FACTOR(CLK_TOP_UNIVPLL3_D2, "univpll3_d2", "univpll", 1, 2),
 96	FACTOR(CLK_TOP_UNIVPLL3_D4, "univpll3_d4", "univpll", 1, 4),
 97	FACTOR(CLK_TOP_MSDCPLL_D2, "msdcpll_d2", "msdcpll", 1, 2),
 98	FACTOR(CLK_TOP_MSDCPLL_D4, "msdcpll_d4", "msdcpll", 1, 4),
 99	FACTOR(CLK_TOP_MSDCPLL_D8, "msdcpll_d8", "msdcpll", 1, 8),
100	FACTOR(CLK_TOP_MSDCPLL_D16, "msdcpll_d16", "msdcpll", 1, 16),
101	FACTOR(CLK_TOP_VENCPLL_D3, "vencpll_d3", "vencpll", 1, 3),
102	FACTOR(CLK_TOP_TVDPLL_D2, "tvdpll_d2", "tvdpll", 1, 2),
103	FACTOR(CLK_TOP_TVDPLL_D4, "tvdpll_d4", "tvdpll", 1, 4),
104	FACTOR(CLK_TOP_DMPLL_D2, "dmpll_d2", "clkph_mck_o", 1, 2),
105	FACTOR(CLK_TOP_DMPLL_D4, "dmpll_d4", "clkph_mck_o", 1, 4),
106	FACTOR(CLK_TOP_DMPLL_D8, "dmpll_d8", "clkph_mck_o", 1, 8),
107	FACTOR(CLK_TOP_AD_SYS_26M_D2, "ad_sys_26m_d2", "clk26m", 1, 2)
108};
109
110static const char * const axi_sel_parents[] = {
111	"clk26m",
112	"syspll1_d2",
113	"syspll_d5",
114	"syspll1_d4",
115	"univpll_d5",
116	"univpll2_d2",
117	"dmpll",
118	"dmpll_d2"
119};
120
121static const char * const mem_sel_parents[] = {
122	"clk26m",
123	"dmpll"
124};
125
126static const char * const ddrphycfg_parents[] = {
127	"clk26m",
128	"syspll1_d8"
129};
130
131static const char * const mm_sel_parents[] = {
132	"clk26m",
133	"vencpll",
134	"syspll1_d2",
135	"syspll_d5",
136	"syspll1_d4",
137	"univpll_d5",
138	"univpll2_d2",
139	"dmpll"
140};
141
142static const char * const pwm_sel_parents[] = {
143	"clk26m",
144	"univpll2_d4",
145	"univpll3_d2",
146	"univpll1_d4"
147};
148
149static const char * const vdec_sel_parents[] = {
150	"clk26m",
151	"syspll1_d2",
152	"syspll_d5",
153	"syspll1_d4",
154	"univpll_d5",
155	"syspll_d2",
156	"syspll2_d2",
157	"msdcpll_d2"
158};
159
160static const char * const mfg_sel_parents[] = {
161	"clk26m",
162	"mmpll",
163	"clk26m",
164	"clk26m",
165	"clk26m",
166	"clk26m",
167	"clk26m",
168	"clk26m",
169	"clk26m",
170	"syspll_d3",
171	"syspll1_d2",
172	"syspll_d5",
173	"univpll_d3",
174	"univpll1_d2"
175};
176
177static const char * const camtg_sel_parents[] = {
178	"clk26m",
179	"univpll_d26",
180	"univpll2_d2",
181	"syspll3_d2",
182	"syspll3_d4",
183	"msdcpll_d4"
184};
185
186static const char * const uart_sel_parents[] = {
187	"clk26m",
188	"univpll2_d8"
189};
190
191static const char * const spi_sel_parents[] = {
192	"clk26m",
193	"syspll3_d2",
194	"msdcpll_d8",
195	"syspll2_d4",
196	"syspll4_d2",
197	"univpll2_d4",
198	"univpll1_d8"
199};
200
201static const char * const usb20_sel_parents[] = {
202	"clk26m",
203	"univpll1_d8",
204	"univpll3_d4"
205};
206
207static const char * const msdc50_0_sel_parents[] = {
208	"clk26m",
209	"syspll1_d2",
210	"syspll2_d2",
211	"syspll4_d2",
212	"univpll_d5",
213	"univpll1_d4"
214};
215
216static const char * const msdc30_0_sel_parents[] = {
217	"clk26m",
218	"msdcpll",
219	"msdcpll_d2",
220	"msdcpll_d4",
221	"syspll2_d2",
222	"syspll1_d4",
223	"univpll1_d4",
224	"univpll_d3",
225	"univpll_d26",
226	"syspll2_d4",
227	"univpll_d2"
228};
229
230static const char * const msdc30_1_2_sel_parents[] = {
231	"clk26m",
232	"univpll2_d2",
233	"msdcpll_d4",
234	"syspll2_d2",
235	"syspll1_d4",
236	"univpll1_d4",
237	"univpll_d26",
238	"syspll2_d4"
239};
240
241static const char * const msdc30_3_sel_parents[] = {
242	"clk26m",
243	"univpll2_d2",
244	"msdcpll_d4",
245	"syspll2_d2",
246	"syspll1_d4",
247	"univpll1_d4",
248	"univpll_d26",
249	"msdcpll_d16",
250	"syspll2_d4"
251};
252
253static const char * const audio_sel_parents[] = {
254	"clk26m",
255	"syspll3_d4",
256	"syspll4_d4",
257	"syspll1_d16"
258};
259
260static const char * const aud_intbus_sel_parents[] = {
261	"clk26m",
262	"syspll1_d4",
263	"syspll4_d2",
264	"dmpll_d4"
265};
266
267static const char * const pmicspi_sel_parents[] = {
268	"clk26m",
269	"syspll1_d8",
270	"syspll3_d4",
271	"syspll1_d16",
272	"univpll3_d4",
273	"univpll_d26",
274	"dmpll_d4",
275	"dmpll_d8"
276};
277
278static const char * const scp_sel_parents[] = {
279	"clk26m",
280	"syspll1_d8",
281	"dmpll_d2",
282	"dmpll_d4"
283};
284
285static const char * const atb_sel_parents[] = {
286	"clk26m",
287	"syspll1_d2",
288	"syspll_d5",
289	"dmpll"
290};
291
292static const char * const dpi0_sel_parents[] = {
293	"clk26m",
294	"tvdpll",
295	"tvdpll_d2",
296	"tvdpll_d4",
297	"dpi_ck"
298};
299
300static const char * const scam_sel_parents[] = {
301	"clk26m",
302	"syspll3_d2",
303	"univpll2_d4",
304	"vencpll_d3"
305};
306
307static const char * const mfg13m_sel_parents[] = {
308	"clk26m",
309	"ad_sys_26m_d2"
310};
311
312static const char * const aud_1_2_sel_parents[] = {
313	"clk26m",
314	"apll1"
315};
316
317static const char * const irda_sel_parents[] = {
318	"clk26m",
319	"univpll2_d4"
320};
321
322static const char * const irtx_sel_parents[] = {
323	"clk26m",
324	"ad_sys_26m_ck"
325};
326
327static const char * const disppwm_sel_parents[] = {
328	"clk26m",
329	"univpll2_d4",
330	"syspll4_d2_d8",
331	"ad_sys_26m_ck"
332};
333
334static const struct mtk_mux topckgen_muxes[] = {
335	MUX_CLR_SET_UPD(CLK_TOP_AXI_SEL, "axi_sel", axi_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 0, 3, 0, 0),
336	MUX_CLR_SET_UPD(CLK_TOP_MEM_SEL, "mem_sel", mem_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 8, 1, 0, 0),
337	MUX_CLR_SET_UPD(CLK_TOP_DDRPHY_SEL, "ddrphycfg_sel", ddrphycfg_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 16, 1, 0, 0),
338	MUX_GATE_CLR_SET_UPD(CLK_TOP_MM_SEL, "mm_sel", mm_sel_parents, CLK_CFG_0, CLK_CFG_0_SET, CLK_CFG_0_CLR, 24, 3, 31, 0, 0),
339	MUX_GATE_CLR_SET_UPD(CLK_TOP_PWM_SEL, "pwm_sel", pwm_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 0, 2, 7, 0, 0),
340	MUX_GATE_CLR_SET_UPD(CLK_TOP_VDEC_SEL, "vdec_sel", vdec_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 8, 3, 15, 0, 0),
341	MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG_SEL, "mfg_sel", mfg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 16, 4, 23, 0, 0),
342	MUX_GATE_CLR_SET_UPD(CLK_TOP_CAMTG_SEL, "camtg_sel", camtg_sel_parents, CLK_CFG_1, CLK_CFG_1_SET, CLK_CFG_1_CLR, 24, 3, 31, 0, 0),
343	MUX_GATE_CLR_SET_UPD(CLK_TOP_UART_SEL, "uart_sel", uart_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 0, 1, 7, 0, 0),
344	MUX_GATE_CLR_SET_UPD(CLK_TOP_SPI_SEL, "spi_sel", spi_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 8, 3, 15, 0, 0),
345	MUX_GATE_CLR_SET_UPD(CLK_TOP_USB20_SEL, "usb20_sel", usb20_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 16, 2, 23, 0, 0),
346	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC50_0_SEL, "msdc50_0_sel", msdc50_0_sel_parents, CLK_CFG_2, CLK_CFG_2_SET, CLK_CFG_2_CLR, 24, 3, 31, 0, 0),
347	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_0_SEL, "msdc30_0_sel", msdc30_0_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 0, 4, 7, 0, 0),
348	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_1_SEL, "msdc30_1_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 8, 3, 15, 0, 0),
349	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_2_SEL, "msdc30_2_sel", msdc30_1_2_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 16, 3, 23, 0, 0),
350	MUX_GATE_CLR_SET_UPD(CLK_TOP_MSDC30_3_SEL, "msdc30_3_sel", msdc30_3_sel_parents, CLK_CFG_3, CLK_CFG_3_SET, CLK_CFG_3_CLR, 24, 4, 31, 0, 0),
351	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDIO_SEL, "audio_sel", audio_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 0, 2, 7, 0, 0),
352	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUDINTBUS_SEL, "aud_intbus_sel", aud_intbus_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 8, 2, 15, 0, 0),
353	MUX_CLR_SET_UPD(CLK_TOP_PMICSPI_SEL, "pmicspi_sel", pmicspi_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 16, 3, 0, 0),
354	MUX_GATE_CLR_SET_UPD(CLK_TOP_SCP_SEL, "scp_sel", scp_sel_parents, CLK_CFG_4, CLK_CFG_4_SET, CLK_CFG_4_CLR, 24, 2, 31, 0, 0),
355	MUX_GATE_CLR_SET_UPD(CLK_TOP_ATB_SEL, "atb_sel", atb_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 0, 2, 7, 0, 0),
356	MUX_GATE_CLR_SET_UPD(CLK_TOP_DPI0_SEL, "dpi0_sel", dpi0_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 8, 3, 15, 0, 0),
357	MUX_GATE_CLR_SET_UPD(CLK_TOP_SCAM_SEL, "scam_sel", scam_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 16, 2, 23, 0, 0),
358	MUX_GATE_CLR_SET_UPD(CLK_TOP_MFG13M_SEL, "mfg13m_sel", mfg13m_sel_parents, CLK_CFG_5, CLK_CFG_5_SET, CLK_CFG_5_CLR, 24, 1, 31, 0, 0),
359	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD1_SEL, "aud_1_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 0, 1, 7, 0, 0),
360	MUX_GATE_CLR_SET_UPD(CLK_TOP_AUD2_SEL, "aud_2_sel", aud_1_2_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 8, 1, 15, 0, 0),
361	MUX_GATE_CLR_SET_UPD(CLK_TOP_IRDA_SEL, "irda_sel", irda_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 16, 1, 23, 0, 0),
362	MUX_GATE_CLR_SET_UPD(CLK_TOP_IRTX_SEL, "irtx_sel", irtx_sel_parents, CLK_CFG_6, CLK_CFG_6_SET, CLK_CFG_6_CLR, 24, 1, 31, 0, 0),
363	MUX_GATE_CLR_SET_UPD(CLK_TOP_DISPPWM_SEL, "disppwm_sel", disppwm_sel_parents, CLK_CFG_7, CLK_CFG_7_SET, CLK_CFG_7_CLR, 0, 2, 7, 0, 0),
364};
365
366static const struct mtk_clk_desc topckgen_desc = {
367	.fixed_clks = topckgen_fixed_clks,
368	.num_fixed_clks = ARRAY_SIZE(topckgen_fixed_clks),
369	.factor_clks = topckgen_factors,
370	.num_factor_clks = ARRAY_SIZE(topckgen_factors),
371	.mux_clks = topckgen_muxes,
372	.num_mux_clks = ARRAY_SIZE(topckgen_muxes),
373	.clk_lock = &mt6735_topckgen_lock,
374};
375
376static const struct of_device_id of_match_mt6735_topckgen[] = {
377	{ .compatible = "mediatek,mt6735-topckgen", .data = &topckgen_desc},
378	{ /* sentinel */ }
379};
380MODULE_DEVICE_TABLE(of, of_match_mt6735_topckgen);
381
382static struct platform_driver clk_mt6735_topckgen = {
383	.probe = mtk_clk_simple_probe,
384	.remove = mtk_clk_simple_remove,
385	.driver = {
386		.name = "clk-mt6735-topckgen",
387		.of_match_table = of_match_mt6735_topckgen,
388	},
389};
390module_platform_driver(clk_mt6735_topckgen);
391
392MODULE_AUTHOR("Yassine Oudjana <y.oudjana@protonmail.com>");
393MODULE_DESCRIPTION("MediaTek MT6735 topckgen clock driver");
394MODULE_LICENSE("GPL");
~/ Read-only file preview.