• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Ingenic JZ4755 SoC CGU driver
4  * Heavily based on JZ4725b CGU driver
5  *
6  * Copyright (C) 2022 Siarhei Volkau
7  * Author: Siarhei Volkau <lis8215@gmail.com>
8  */
9 
10 #include <linux/clk-provider.h>
11 #include <linux/delay.h>
12 #include <linux/of.h>
13 
14 #include <dt-bindings/clock/ingenic,jz4755-cgu.h>
15 
16 #include "cgu.h"
17 #include "pm.h"
18 
19 /* CGU register offsets */
20 #define CGU_REG_CPCCR		0x00
21 #define CGU_REG_CPPCR		0x10
22 #define CGU_REG_CLKGR		0x20
23 #define CGU_REG_OPCR		0x24
24 #define CGU_REG_I2SCDR		0x60
25 #define CGU_REG_LPCDR		0x64
26 #define CGU_REG_MSCCDR		0x68
27 #define CGU_REG_SSICDR		0x74
28 #define CGU_REG_CIMCDR		0x7C
29 
30 static struct ingenic_cgu *cgu;
31 
32 static const s8 pll_od_encoding[4] = {
33 	0x0, 0x1, -1, 0x3,
34 };
35 
36 static const u8 jz4755_cgu_cpccr_div_table[] = {
37 	1, 2, 3, 4, 6, 8,
38 };
39 
40 static const u8 jz4755_cgu_pll_half_div_table[] = {
41 	2, 1,
42 };
43 
44 static const struct ingenic_cgu_clk_info jz4755_cgu_clocks[] = {
45 
46 	/* External clocks */
47 
48 	[JZ4755_CLK_EXT] = { "ext", CGU_CLK_EXT },
49 	[JZ4755_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
50 
51 	[JZ4755_CLK_PLL] = {
52 		"pll", CGU_CLK_PLL,
53 		.parents = { JZ4755_CLK_EXT, },
54 		.pll = {
55 			.reg = CGU_REG_CPPCR,
56 			.rate_multiplier = 1,
57 			.m_shift = 23,
58 			.m_bits = 9,
59 			.m_offset = 2,
60 			.n_shift = 18,
61 			.n_bits = 5,
62 			.n_offset = 2,
63 			.od_shift = 16,
64 			.od_bits = 2,
65 			.od_max = 4,
66 			.od_encoding = pll_od_encoding,
67 			.stable_bit = 10,
68 			.bypass_reg = CGU_REG_CPPCR,
69 			.bypass_bit = 9,
70 			.enable_bit = 8,
71 		},
72 	},
73 
74 	/* Muxes & dividers */
75 
76 	[JZ4755_CLK_PLL_HALF] = {
77 		"pll half", CGU_CLK_DIV,
78 		.parents = { JZ4755_CLK_PLL, },
79 		.div = {
80 			CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
81 			jz4755_cgu_pll_half_div_table,
82 		},
83 	},
84 
85 	[JZ4755_CLK_EXT_HALF] = {
86 		"ext half", CGU_CLK_DIV,
87 		.parents = { JZ4755_CLK_EXT, },
88 		.div = {
89 			CGU_REG_CPCCR, 30, 1, 1, -1, -1, -1, 0,
90 			NULL,
91 		},
92 	},
93 
94 	[JZ4755_CLK_CCLK] = {
95 		"cclk", CGU_CLK_DIV,
96 		.parents = { JZ4755_CLK_PLL, },
97 		.div = {
98 			CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
99 			jz4755_cgu_cpccr_div_table,
100 		},
101 	},
102 
103 	[JZ4755_CLK_H0CLK] = {
104 		"hclk", CGU_CLK_DIV,
105 		.parents = { JZ4755_CLK_PLL, },
106 		.div = {
107 			CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
108 			jz4755_cgu_cpccr_div_table,
109 		},
110 	},
111 
112 	[JZ4755_CLK_PCLK] = {
113 		"pclk", CGU_CLK_DIV,
114 		.parents = { JZ4755_CLK_PLL, },
115 		.div = {
116 			CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
117 			jz4755_cgu_cpccr_div_table,
118 		},
119 	},
120 
121 	[JZ4755_CLK_MCLK] = {
122 		"mclk", CGU_CLK_DIV,
123 		.parents = { JZ4755_CLK_PLL, },
124 		.div = {
125 			CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
126 			jz4755_cgu_cpccr_div_table,
127 		},
128 	},
129 
130 	[JZ4755_CLK_H1CLK] = {
131 		"h1clk", CGU_CLK_DIV,
132 		.parents = { JZ4755_CLK_PLL, },
133 		.div = {
134 			CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
135 			jz4755_cgu_cpccr_div_table,
136 		},
137 	},
138 
139 	[JZ4755_CLK_UDC] = {
140 		"udc", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
141 		.parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },
142 		.mux = { CGU_REG_CPCCR, 29, 1 },
143 		.div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
144 		.gate = { CGU_REG_CLKGR, 10 },
145 	},
146 
147 	[JZ4755_CLK_LCD] = {
148 		"lcd", CGU_CLK_DIV | CGU_CLK_GATE,
149 		.parents = { JZ4755_CLK_PLL_HALF, },
150 		.div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
151 		.gate = { CGU_REG_CLKGR, 9 },
152 	},
153 
154 	[JZ4755_CLK_MMC] = {
155 		"mmc", CGU_CLK_DIV,
156 		.parents = { JZ4755_CLK_PLL_HALF, },
157 		.div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
158 	},
159 
160 	[JZ4755_CLK_I2S] = {
161 		"i2s", CGU_CLK_MUX | CGU_CLK_DIV,
162 		.parents = { JZ4755_CLK_EXT_HALF, JZ4755_CLK_PLL_HALF, },
163 		.mux = { CGU_REG_CPCCR, 31, 1 },
164 		.div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1 },
165 	},
166 
167 	[JZ4755_CLK_SPI] = {
168 		"spi", CGU_CLK_DIV | CGU_CLK_GATE,
169 		.parents = { JZ4755_CLK_PLL_HALF, },
170 		.div = { CGU_REG_SSICDR, 0, 1, 4, -1, -1, -1 },
171 		.gate = { CGU_REG_CLKGR, 4 },
172 	},
173 
174 	[JZ4755_CLK_TVE] = {
175 		"tve", CGU_CLK_MUX | CGU_CLK_GATE,
176 		.parents = { JZ4755_CLK_LCD, JZ4755_CLK_EXT, },
177 		.mux = { CGU_REG_LPCDR, 31, 1 },
178 		.gate = { CGU_REG_CLKGR, 18 },
179 	},
180 
181 	[JZ4755_CLK_RTC] = {
182 		"rtc", CGU_CLK_MUX | CGU_CLK_GATE,
183 		.parents = { JZ4755_CLK_EXT512, JZ4755_CLK_OSC32K, },
184 		.mux = { CGU_REG_OPCR, 2, 1},
185 		.gate = { CGU_REG_CLKGR, 2 },
186 	},
187 
188 	[JZ4755_CLK_CIM] = {
189 		"cim", CGU_CLK_DIV | CGU_CLK_GATE,
190 		.parents = { JZ4755_CLK_PLL_HALF, },
191 		.div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
192 		.gate = { CGU_REG_CLKGR, 8 },
193 	},
194 
195 	/* Gate-only clocks */
196 
197 	[JZ4755_CLK_UART0] = {
198 		"uart0", CGU_CLK_GATE,
199 		.parents = { JZ4755_CLK_EXT_HALF, },
200 		.gate = { CGU_REG_CLKGR, 0 },
201 	},
202 
203 	[JZ4755_CLK_UART1] = {
204 		"uart1", CGU_CLK_GATE,
205 		.parents = { JZ4755_CLK_EXT_HALF, },
206 		.gate = { CGU_REG_CLKGR, 14 },
207 	},
208 
209 	[JZ4755_CLK_UART2] = {
210 		"uart2", CGU_CLK_GATE,
211 		.parents = { JZ4755_CLK_EXT_HALF, },
212 		.gate = { CGU_REG_CLKGR, 15 },
213 	},
214 
215 	[JZ4755_CLK_ADC] = {
216 		"adc", CGU_CLK_GATE,
217 		.parents = { JZ4755_CLK_EXT_HALF, },
218 		.gate = { CGU_REG_CLKGR, 7 },
219 	},
220 
221 	[JZ4755_CLK_AIC] = {
222 		"aic", CGU_CLK_GATE,
223 		.parents = { JZ4755_CLK_EXT_HALF, },
224 		.gate = { CGU_REG_CLKGR, 5 },
225 	},
226 
227 	[JZ4755_CLK_I2C] = {
228 		"i2c", CGU_CLK_GATE,
229 		.parents = { JZ4755_CLK_EXT_HALF, },
230 		.gate = { CGU_REG_CLKGR, 3 },
231 	},
232 
233 	[JZ4755_CLK_BCH] = {
234 		"bch", CGU_CLK_GATE,
235 		.parents = { JZ4755_CLK_H1CLK, },
236 		.gate = { CGU_REG_CLKGR, 11 },
237 	},
238 
239 	[JZ4755_CLK_TCU] = {
240 		"tcu", CGU_CLK_GATE,
241 		.parents = { JZ4755_CLK_EXT, },
242 		.gate = { CGU_REG_CLKGR, 1 },
243 	},
244 
245 	[JZ4755_CLK_DMA] = {
246 		"dma", CGU_CLK_GATE,
247 		.parents = { JZ4755_CLK_PCLK, },
248 		.gate = { CGU_REG_CLKGR, 12 },
249 	},
250 
251 	[JZ4755_CLK_MMC0] = {
252 		"mmc0", CGU_CLK_GATE,
253 		.parents = { JZ4755_CLK_MMC, },
254 		.gate = { CGU_REG_CLKGR, 6 },
255 	},
256 
257 	[JZ4755_CLK_MMC1] = {
258 		"mmc1", CGU_CLK_GATE,
259 		.parents = { JZ4755_CLK_MMC, },
260 		.gate = { CGU_REG_CLKGR, 16 },
261 	},
262 
263 	[JZ4755_CLK_AUX_CPU] = {
264 		"aux_cpu", CGU_CLK_GATE,
265 		.parents = { JZ4755_CLK_H1CLK, },
266 		.gate = { CGU_REG_CLKGR, 24 },
267 	},
268 
269 	[JZ4755_CLK_AHB1] = {
270 		"ahb1", CGU_CLK_GATE,
271 		.parents = { JZ4755_CLK_H1CLK, },
272 		.gate = { CGU_REG_CLKGR, 23 },
273 	},
274 
275 	[JZ4755_CLK_IDCT] = {
276 		"idct", CGU_CLK_GATE,
277 		.parents = { JZ4755_CLK_H1CLK, },
278 		.gate = { CGU_REG_CLKGR, 22 },
279 	},
280 
281 	[JZ4755_CLK_DB] = {
282 		"db", CGU_CLK_GATE,
283 		.parents = { JZ4755_CLK_H1CLK, },
284 		.gate = { CGU_REG_CLKGR, 21 },
285 	},
286 
287 	[JZ4755_CLK_ME] = {
288 		"me", CGU_CLK_GATE,
289 		.parents = { JZ4755_CLK_H1CLK, },
290 		.gate = { CGU_REG_CLKGR, 20 },
291 	},
292 
293 	[JZ4755_CLK_MC] = {
294 		"mc", CGU_CLK_GATE,
295 		.parents = { JZ4755_CLK_H1CLK, },
296 		.gate = { CGU_REG_CLKGR, 19 },
297 	},
298 
299 	[JZ4755_CLK_TSSI] = {
300 		"tssi", CGU_CLK_GATE,
301 		.parents = { JZ4755_CLK_EXT_HALF/* not sure */, },
302 		.gate = { CGU_REG_CLKGR, 17 },
303 	},
304 
305 	[JZ4755_CLK_IPU] = {
306 		"ipu", CGU_CLK_GATE,
307 		.parents = { JZ4755_CLK_PLL_HALF/* not sure */, },
308 		.gate = { CGU_REG_CLKGR, 13 },
309 	},
310 
311 	[JZ4755_CLK_EXT512] = {
312 		"ext/512", CGU_CLK_FIXDIV,
313 		.parents = { JZ4755_CLK_EXT, },
314 
315 		.fixdiv = { 512 },
316 	},
317 
318 	[JZ4755_CLK_UDC_PHY] = {
319 		"udc_phy", CGU_CLK_GATE,
320 		.parents = { JZ4755_CLK_EXT_HALF, },
321 		.gate = { CGU_REG_OPCR, 6, true },
322 	},
323 };
324 
jz4755_cgu_init(struct device_node * np)325 static void __init jz4755_cgu_init(struct device_node *np)
326 {
327 	int retval;
328 
329 	cgu = ingenic_cgu_new(jz4755_cgu_clocks,
330 			      ARRAY_SIZE(jz4755_cgu_clocks), np);
331 	if (!cgu) {
332 		pr_err("%s: failed to initialise CGU\n", __func__);
333 		return;
334 	}
335 
336 	retval = ingenic_cgu_register_clocks(cgu);
337 	if (retval)
338 		pr_err("%s: failed to register CGU Clocks\n", __func__);
339 
340 	ingenic_cgu_register_syscore_ops(cgu);
341 }
342 /*
343  * CGU has some children devices, this is useful for probing children devices
344  * in the case where the device node is compatible with "simple-mfd".
345  */
346 CLK_OF_DECLARE_DRIVER(jz4755_cgu, "ingenic,jz4755-cgu", jz4755_cgu_init);
347