f2c2d848dab7a916f60a90854a6bee1d370fef08
[releases.git] / jz4755-cgu.c
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
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);