1 // SPDX-License-Identifier: GPL-2.0
3 * Ingenic JZ4755 SoC CGU driver
4 * Heavily based on JZ4725b CGU driver
6 * Copyright (C) 2022 Siarhei Volkau
7 * Author: Siarhei Volkau <lis8215@gmail.com>
10 #include <linux/clk-provider.h>
11 #include <linux/delay.h>
14 #include <dt-bindings/clock/ingenic,jz4755-cgu.h>
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
30 static struct ingenic_cgu *cgu;
32 static const s8 pll_od_encoding[4] = {
36 static const u8 jz4755_cgu_cpccr_div_table[] = {
40 static const u8 jz4755_cgu_pll_half_div_table[] = {
44 static const struct ingenic_cgu_clk_info jz4755_cgu_clocks[] = {
48 [JZ4755_CLK_EXT] = { "ext", CGU_CLK_EXT },
49 [JZ4755_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
53 .parents = { JZ4755_CLK_EXT, },
66 .od_encoding = pll_od_encoding,
68 .bypass_reg = CGU_REG_CPPCR,
74 /* Muxes & dividers */
76 [JZ4755_CLK_PLL_HALF] = {
77 "pll half", CGU_CLK_DIV,
78 .parents = { JZ4755_CLK_PLL, },
80 CGU_REG_CPCCR, 21, 1, 1, -1, -1, -1, 0,
81 jz4755_cgu_pll_half_div_table,
85 [JZ4755_CLK_EXT_HALF] = {
86 "ext half", CGU_CLK_DIV,
87 .parents = { JZ4755_CLK_EXT, },
89 CGU_REG_CPCCR, 30, 1, 1, -1, -1, -1, 0,
96 .parents = { JZ4755_CLK_PLL, },
98 CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
99 jz4755_cgu_cpccr_div_table,
103 [JZ4755_CLK_H0CLK] = {
105 .parents = { JZ4755_CLK_PLL, },
107 CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
108 jz4755_cgu_cpccr_div_table,
112 [JZ4755_CLK_PCLK] = {
114 .parents = { JZ4755_CLK_PLL, },
116 CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
117 jz4755_cgu_cpccr_div_table,
121 [JZ4755_CLK_MCLK] = {
123 .parents = { JZ4755_CLK_PLL, },
125 CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
126 jz4755_cgu_cpccr_div_table,
130 [JZ4755_CLK_H1CLK] = {
131 "h1clk", CGU_CLK_DIV,
132 .parents = { JZ4755_CLK_PLL, },
134 CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
135 jz4755_cgu_cpccr_div_table,
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 },
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 },
156 .parents = { JZ4755_CLK_PLL_HALF, },
157 .div = { CGU_REG_MSCCDR, 0, 1, 5, -1, -1, -1 },
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 },
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 },
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 },
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 },
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 },
195 /* Gate-only clocks */
197 [JZ4755_CLK_UART0] = {
198 "uart0", CGU_CLK_GATE,
199 .parents = { JZ4755_CLK_EXT_HALF, },
200 .gate = { CGU_REG_CLKGR, 0 },
203 [JZ4755_CLK_UART1] = {
204 "uart1", CGU_CLK_GATE,
205 .parents = { JZ4755_CLK_EXT_HALF, },
206 .gate = { CGU_REG_CLKGR, 14 },
209 [JZ4755_CLK_UART2] = {
210 "uart2", CGU_CLK_GATE,
211 .parents = { JZ4755_CLK_EXT_HALF, },
212 .gate = { CGU_REG_CLKGR, 15 },
217 .parents = { JZ4755_CLK_EXT_HALF, },
218 .gate = { CGU_REG_CLKGR, 7 },
223 .parents = { JZ4755_CLK_EXT_HALF, },
224 .gate = { CGU_REG_CLKGR, 5 },
229 .parents = { JZ4755_CLK_EXT_HALF, },
230 .gate = { CGU_REG_CLKGR, 3 },
235 .parents = { JZ4755_CLK_H1CLK, },
236 .gate = { CGU_REG_CLKGR, 11 },
241 .parents = { JZ4755_CLK_EXT, },
242 .gate = { CGU_REG_CLKGR, 1 },
247 .parents = { JZ4755_CLK_PCLK, },
248 .gate = { CGU_REG_CLKGR, 12 },
251 [JZ4755_CLK_MMC0] = {
252 "mmc0", CGU_CLK_GATE,
253 .parents = { JZ4755_CLK_MMC, },
254 .gate = { CGU_REG_CLKGR, 6 },
257 [JZ4755_CLK_MMC1] = {
258 "mmc1", CGU_CLK_GATE,
259 .parents = { JZ4755_CLK_MMC, },
260 .gate = { CGU_REG_CLKGR, 16 },
263 [JZ4755_CLK_AUX_CPU] = {
264 "aux_cpu", CGU_CLK_GATE,
265 .parents = { JZ4755_CLK_H1CLK, },
266 .gate = { CGU_REG_CLKGR, 24 },
269 [JZ4755_CLK_AHB1] = {
270 "ahb1", CGU_CLK_GATE,
271 .parents = { JZ4755_CLK_H1CLK, },
272 .gate = { CGU_REG_CLKGR, 23 },
275 [JZ4755_CLK_IDCT] = {
276 "idct", CGU_CLK_GATE,
277 .parents = { JZ4755_CLK_H1CLK, },
278 .gate = { CGU_REG_CLKGR, 22 },
283 .parents = { JZ4755_CLK_H1CLK, },
284 .gate = { CGU_REG_CLKGR, 21 },
289 .parents = { JZ4755_CLK_H1CLK, },
290 .gate = { CGU_REG_CLKGR, 20 },
295 .parents = { JZ4755_CLK_H1CLK, },
296 .gate = { CGU_REG_CLKGR, 19 },
299 [JZ4755_CLK_TSSI] = {
300 "tssi", CGU_CLK_GATE,
301 .parents = { JZ4755_CLK_EXT_HALF/* not sure */, },
302 .gate = { CGU_REG_CLKGR, 17 },
307 .parents = { JZ4755_CLK_PLL_HALF/* not sure */, },
308 .gate = { CGU_REG_CLKGR, 13 },
311 [JZ4755_CLK_EXT512] = {
312 "ext/512", CGU_CLK_FIXDIV,
313 .parents = { JZ4755_CLK_EXT, },
318 [JZ4755_CLK_UDC_PHY] = {
319 "udc_phy", CGU_CLK_GATE,
320 .parents = { JZ4755_CLK_EXT_HALF, },
321 .gate = { CGU_REG_OPCR, 6, true },
325 static void __init jz4755_cgu_init(struct device_node *np)
329 cgu = ingenic_cgu_new(jz4755_cgu_clocks,
330 ARRAY_SIZE(jz4755_cgu_clocks), np);
332 pr_err("%s: failed to initialise CGU\n", __func__);
336 retval = ingenic_cgu_register_clocks(cgu);
338 pr_err("%s: failed to register CGU Clocks\n", __func__);
340 ingenic_cgu_register_syscore_ops(cgu);
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".
346 CLK_OF_DECLARE_DRIVER(jz4755_cgu, "ingenic,jz4755-cgu", jz4755_cgu_init);