xref: /openbmc/linux/drivers/clk/ingenic/x1000-cgu.c (revision 82df5b73)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * X1000 SoC CGU driver
4  * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
5  */
6 
7 #include <linux/clk-provider.h>
8 #include <linux/delay.h>
9 #include <linux/io.h>
10 #include <linux/of.h>
11 
12 #include <dt-bindings/clock/x1000-cgu.h>
13 
14 #include "cgu.h"
15 #include "pm.h"
16 
17 /* CGU register offsets */
18 #define CGU_REG_CPCCR		0x00
19 #define CGU_REG_APLL		0x10
20 #define CGU_REG_MPLL		0x14
21 #define CGU_REG_CLKGR		0x20
22 #define CGU_REG_OPCR		0x24
23 #define CGU_REG_DDRCDR		0x2c
24 #define CGU_REG_USBPCR		0x3c
25 #define CGU_REG_USBPCR1		0x48
26 #define CGU_REG_USBCDR		0x50
27 #define CGU_REG_MACCDR		0x54
28 #define CGU_REG_I2SCDR		0x60
29 #define CGU_REG_LPCDR		0x64
30 #define CGU_REG_MSC0CDR		0x68
31 #define CGU_REG_I2SCDR1		0x70
32 #define CGU_REG_SSICDR		0x74
33 #define CGU_REG_CIMCDR		0x7c
34 #define CGU_REG_PCMCDR		0x84
35 #define CGU_REG_MSC1CDR		0xa4
36 #define CGU_REG_CMP_INTR	0xb0
37 #define CGU_REG_CMP_INTRE	0xb4
38 #define CGU_REG_DRCG		0xd0
39 #define CGU_REG_CPCSR		0xd4
40 #define CGU_REG_PCMCDR1		0xe0
41 #define CGU_REG_MACPHYC		0xe8
42 
43 /* bits within the OPCR register */
44 #define OPCR_SPENDN0		BIT(7)
45 #define OPCR_SPENDN1		BIT(6)
46 
47 /* bits within the USBPCR register */
48 #define USBPCR_SIDDQ		BIT(21)
49 #define USBPCR_OTG_DISABLE	BIT(20)
50 
51 static struct ingenic_cgu *cgu;
52 
53 static int x1000_usb_phy_enable(struct clk_hw *hw)
54 {
55 	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
56 	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
57 
58 	writel(readl(reg_opcr) | OPCR_SPENDN0, reg_opcr);
59 	writel(readl(reg_usbpcr) & ~USBPCR_OTG_DISABLE & ~USBPCR_SIDDQ, reg_usbpcr);
60 	return 0;
61 }
62 
63 static void x1000_usb_phy_disable(struct clk_hw *hw)
64 {
65 	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
66 	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
67 
68 	writel(readl(reg_opcr) & ~OPCR_SPENDN0, reg_opcr);
69 	writel(readl(reg_usbpcr) | USBPCR_OTG_DISABLE | USBPCR_SIDDQ, reg_usbpcr);
70 }
71 
72 static int x1000_usb_phy_is_enabled(struct clk_hw *hw)
73 {
74 	void __iomem *reg_opcr		= cgu->base + CGU_REG_OPCR;
75 	void __iomem *reg_usbpcr	= cgu->base + CGU_REG_USBPCR;
76 
77 	return (readl(reg_opcr) & OPCR_SPENDN0) &&
78 		!(readl(reg_usbpcr) & USBPCR_SIDDQ) &&
79 		!(readl(reg_usbpcr) & USBPCR_OTG_DISABLE);
80 }
81 
82 static const struct clk_ops x1000_otg_phy_ops = {
83 	.enable		= x1000_usb_phy_enable,
84 	.disable	= x1000_usb_phy_disable,
85 	.is_enabled	= x1000_usb_phy_is_enabled,
86 };
87 
88 static const s8 pll_od_encoding[8] = {
89 	0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
90 };
91 
92 static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
93 
94 	/* External clocks */
95 
96 	[X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
97 	[X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
98 
99 	/* PLLs */
100 
101 	[X1000_CLK_APLL] = {
102 		"apll", CGU_CLK_PLL,
103 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
104 		.pll = {
105 			.reg = CGU_REG_APLL,
106 			.rate_multiplier = 1,
107 			.m_shift = 24,
108 			.m_bits = 7,
109 			.m_offset = 1,
110 			.n_shift = 18,
111 			.n_bits = 5,
112 			.n_offset = 1,
113 			.od_shift = 16,
114 			.od_bits = 2,
115 			.od_max = 8,
116 			.od_encoding = pll_od_encoding,
117 			.bypass_reg = CGU_REG_APLL,
118 			.bypass_bit = 9,
119 			.enable_bit = 8,
120 			.stable_bit = 10,
121 		},
122 	},
123 
124 	[X1000_CLK_MPLL] = {
125 		"mpll", CGU_CLK_PLL,
126 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
127 		.pll = {
128 			.reg = CGU_REG_MPLL,
129 			.rate_multiplier = 1,
130 			.m_shift = 24,
131 			.m_bits = 7,
132 			.m_offset = 1,
133 			.n_shift = 18,
134 			.n_bits = 5,
135 			.n_offset = 1,
136 			.od_shift = 16,
137 			.od_bits = 2,
138 			.od_max = 8,
139 			.od_encoding = pll_od_encoding,
140 			.bypass_reg = CGU_REG_MPLL,
141 			.bypass_bit = 6,
142 			.enable_bit = 7,
143 			.stable_bit = 0,
144 		},
145 	},
146 
147 
148 	/* Custom (SoC-specific) OTG PHY */
149 
150 	[X1000_CLK_OTGPHY] = {
151 		"otg_phy", CGU_CLK_CUSTOM,
152 		.parents = { -1, -1, X1000_CLK_EXCLK, -1 },
153 		.custom = { &x1000_otg_phy_ops },
154 	},
155 
156 	/* Muxes & dividers */
157 
158 	[X1000_CLK_SCLKA] = {
159 		"sclk_a", CGU_CLK_MUX,
160 		.parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },
161 		.mux = { CGU_REG_CPCCR, 30, 2 },
162 	},
163 
164 	[X1000_CLK_CPUMUX] = {
165 		"cpu_mux", CGU_CLK_MUX,
166 		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
167 		.mux = { CGU_REG_CPCCR, 28, 2 },
168 	},
169 
170 	[X1000_CLK_CPU] = {
171 		"cpu", CGU_CLK_DIV | CGU_CLK_GATE,
172 		.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
173 		.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
174 		.gate = { CGU_REG_CLKGR, 30 },
175 	},
176 
177 	[X1000_CLK_L2CACHE] = {
178 		"l2cache", CGU_CLK_DIV,
179 		.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
180 		.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
181 	},
182 
183 	[X1000_CLK_AHB0] = {
184 		"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
185 		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
186 		.mux = { CGU_REG_CPCCR, 26, 2 },
187 		.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
188 	},
189 
190 	[X1000_CLK_AHB2PMUX] = {
191 		"ahb2_apb_mux", CGU_CLK_MUX,
192 		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
193 		.mux = { CGU_REG_CPCCR, 24, 2 },
194 	},
195 
196 	[X1000_CLK_AHB2] = {
197 		"ahb2", CGU_CLK_DIV,
198 		.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
199 		.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
200 	},
201 
202 	[X1000_CLK_PCLK] = {
203 		"pclk", CGU_CLK_DIV | CGU_CLK_GATE,
204 		.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
205 		.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
206 		.gate = { CGU_REG_CLKGR, 28 },
207 	},
208 
209 	[X1000_CLK_DDR] = {
210 		"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
211 		.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
212 		.mux = { CGU_REG_DDRCDR, 30, 2 },
213 		.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
214 		.gate = { CGU_REG_CLKGR, 31 },
215 	},
216 
217 	[X1000_CLK_MAC] = {
218 		"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
219 		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
220 		.mux = { CGU_REG_MACCDR, 31, 1 },
221 		.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
222 		.gate = { CGU_REG_CLKGR, 25 },
223 	},
224 
225 	[X1000_CLK_LCD] = {
226 		"lcd", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
227 		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL },
228 		.mux = { CGU_REG_LPCDR, 31, 1 },
229 		.div = { CGU_REG_LPCDR, 0, 1, 8, 28, 27, 26 },
230 		.gate = { CGU_REG_CLKGR, 23 },
231 	},
232 
233 	[X1000_CLK_MSCMUX] = {
234 		"msc_mux", CGU_CLK_MUX,
235 		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
236 		.mux = { CGU_REG_MSC0CDR, 31, 1 },
237 	},
238 
239 	[X1000_CLK_MSC0] = {
240 		"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
241 		.parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
242 		.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
243 		.gate = { CGU_REG_CLKGR, 4 },
244 	},
245 
246 	[X1000_CLK_MSC1] = {
247 		"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
248 		.parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
249 		.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
250 		.gate = { CGU_REG_CLKGR, 5 },
251 	},
252 
253 	[X1000_CLK_OTG] = {
254 		"otg", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
255 		.parents = { X1000_CLK_EXCLK, -1,
256 					 X1000_CLK_APLL, X1000_CLK_MPLL },
257 		.mux = { CGU_REG_USBCDR, 30, 2 },
258 		.div = { CGU_REG_USBCDR, 0, 1, 8, 29, 28, 27 },
259 		.gate = { CGU_REG_CLKGR, 3 },
260 	},
261 
262 	[X1000_CLK_SSIPLL] = {
263 		"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
264 		.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
265 		.mux = { CGU_REG_SSICDR, 31, 1 },
266 		.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
267 	},
268 
269 	[X1000_CLK_SSIPLL_DIV2] = {
270 		"ssi_pll_div2", CGU_CLK_FIXDIV,
271 		.parents = { X1000_CLK_SSIPLL },
272 		.fixdiv = { 2 },
273 	},
274 
275 	[X1000_CLK_SSIMUX] = {
276 		"ssi_mux", CGU_CLK_MUX,
277 		.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL_DIV2, -1, -1 },
278 		.mux = { CGU_REG_SSICDR, 30, 1 },
279 	},
280 
281 	[X1000_CLK_EXCLK_DIV512] = {
282 		"exclk_div512", CGU_CLK_FIXDIV,
283 		.parents = { X1000_CLK_EXCLK },
284 		.fixdiv = { 512 },
285 	},
286 
287 	[X1000_CLK_RTC] = {
288 		"rtc_ercs", CGU_CLK_MUX | CGU_CLK_GATE,
289 		.parents = { X1000_CLK_EXCLK_DIV512, X1000_CLK_RTCLK },
290 		.mux = { CGU_REG_OPCR, 2, 1},
291 		.gate = { CGU_REG_CLKGR, 27 },
292 	},
293 
294 	/* Gate-only clocks */
295 
296 	[X1000_CLK_EMC] = {
297 		"emc", CGU_CLK_GATE,
298 		.parents = { X1000_CLK_AHB2, -1, -1, -1 },
299 		.gate = { CGU_REG_CLKGR, 0 },
300 	},
301 
302 	[X1000_CLK_EFUSE] = {
303 		"efuse", CGU_CLK_GATE,
304 		.parents = { X1000_CLK_AHB2, -1, -1, -1 },
305 		.gate = { CGU_REG_CLKGR, 1 },
306 	},
307 
308 	[X1000_CLK_SFC] = {
309 		"sfc", CGU_CLK_GATE,
310 		.parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
311 		.gate = { CGU_REG_CLKGR, 2 },
312 	},
313 
314 	[X1000_CLK_I2C0] = {
315 		"i2c0", CGU_CLK_GATE,
316 		.parents = { X1000_CLK_PCLK, -1, -1, -1 },
317 		.gate = { CGU_REG_CLKGR, 7 },
318 	},
319 
320 	[X1000_CLK_I2C1] = {
321 		"i2c1", CGU_CLK_GATE,
322 		.parents = { X1000_CLK_PCLK, -1, -1, -1 },
323 		.gate = { CGU_REG_CLKGR, 8 },
324 	},
325 
326 	[X1000_CLK_I2C2] = {
327 		"i2c2", CGU_CLK_GATE,
328 		.parents = { X1000_CLK_PCLK, -1, -1, -1 },
329 		.gate = { CGU_REG_CLKGR, 9 },
330 	},
331 
332 	[X1000_CLK_UART0] = {
333 		"uart0", CGU_CLK_GATE,
334 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
335 		.gate = { CGU_REG_CLKGR, 14 },
336 	},
337 
338 	[X1000_CLK_UART1] = {
339 		"uart1", CGU_CLK_GATE,
340 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
341 		.gate = { CGU_REG_CLKGR, 15 },
342 	},
343 
344 	[X1000_CLK_UART2] = {
345 		"uart2", CGU_CLK_GATE,
346 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
347 		.gate = { CGU_REG_CLKGR, 16 },
348 	},
349 
350 	[X1000_CLK_TCU] = {
351 		"tcu", CGU_CLK_GATE,
352 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
353 		.gate = { CGU_REG_CLKGR, 18 },
354 	},
355 
356 	[X1000_CLK_SSI] = {
357 		"ssi", CGU_CLK_GATE,
358 		.parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
359 		.gate = { CGU_REG_CLKGR, 19 },
360 	},
361 
362 	[X1000_CLK_OST] = {
363 		"ost", CGU_CLK_GATE,
364 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
365 		.gate = { CGU_REG_CLKGR, 20 },
366 	},
367 
368 	[X1000_CLK_PDMA] = {
369 		"pdma", CGU_CLK_GATE,
370 		.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
371 		.gate = { CGU_REG_CLKGR, 21 },
372 	},
373 };
374 
375 static void __init x1000_cgu_init(struct device_node *np)
376 {
377 	int retval;
378 
379 	cgu = ingenic_cgu_new(x1000_cgu_clocks,
380 			      ARRAY_SIZE(x1000_cgu_clocks), np);
381 	if (!cgu) {
382 		pr_err("%s: failed to initialise CGU\n", __func__);
383 		return;
384 	}
385 
386 	retval = ingenic_cgu_register_clocks(cgu);
387 	if (retval) {
388 		pr_err("%s: failed to register CGU Clocks\n", __func__);
389 		return;
390 	}
391 
392 	ingenic_cgu_register_syscore_ops(cgu);
393 }
394 /*
395  * CGU has some children devices, this is useful for probing children devices
396  * in the case where the device node is compatible with "simple-mfd".
397  */
398 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);
399