Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf
[linux-2.6-microblaze.git] / drivers / clk / ingenic / x1000-cgu.c
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         /* Gate-only clocks */
282
283         [X1000_CLK_EMC] = {
284                 "emc", CGU_CLK_GATE,
285                 .parents = { X1000_CLK_AHB2, -1, -1, -1 },
286                 .gate = { CGU_REG_CLKGR, 0 },
287         },
288
289         [X1000_CLK_EFUSE] = {
290                 "efuse", CGU_CLK_GATE,
291                 .parents = { X1000_CLK_AHB2, -1, -1, -1 },
292                 .gate = { CGU_REG_CLKGR, 1 },
293         },
294
295         [X1000_CLK_SFC] = {
296                 "sfc", CGU_CLK_GATE,
297                 .parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
298                 .gate = { CGU_REG_CLKGR, 2 },
299         },
300
301         [X1000_CLK_I2C0] = {
302                 "i2c0", CGU_CLK_GATE,
303                 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
304                 .gate = { CGU_REG_CLKGR, 7 },
305         },
306
307         [X1000_CLK_I2C1] = {
308                 "i2c1", CGU_CLK_GATE,
309                 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
310                 .gate = { CGU_REG_CLKGR, 8 },
311         },
312
313         [X1000_CLK_I2C2] = {
314                 "i2c2", CGU_CLK_GATE,
315                 .parents = { X1000_CLK_PCLK, -1, -1, -1 },
316                 .gate = { CGU_REG_CLKGR, 9 },
317         },
318
319         [X1000_CLK_UART0] = {
320                 "uart0", CGU_CLK_GATE,
321                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
322                 .gate = { CGU_REG_CLKGR, 14 },
323         },
324
325         [X1000_CLK_UART1] = {
326                 "uart1", CGU_CLK_GATE,
327                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
328                 .gate = { CGU_REG_CLKGR, 15 },
329         },
330
331         [X1000_CLK_UART2] = {
332                 "uart2", CGU_CLK_GATE,
333                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
334                 .gate = { CGU_REG_CLKGR, 16 },
335         },
336
337         [X1000_CLK_TCU] = {
338                 "tcu", CGU_CLK_GATE,
339                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
340                 .gate = { CGU_REG_CLKGR, 18 },
341         },
342
343         [X1000_CLK_SSI] = {
344                 "ssi", CGU_CLK_GATE,
345                 .parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
346                 .gate = { CGU_REG_CLKGR, 19 },
347         },
348
349         [X1000_CLK_OST] = {
350                 "ost", CGU_CLK_GATE,
351                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
352                 .gate = { CGU_REG_CLKGR, 20 },
353         },
354
355         [X1000_CLK_PDMA] = {
356                 "pdma", CGU_CLK_GATE,
357                 .parents = { X1000_CLK_EXCLK, -1, -1, -1 },
358                 .gate = { CGU_REG_CLKGR, 21 },
359         },
360 };
361
362 static void __init x1000_cgu_init(struct device_node *np)
363 {
364         int retval;
365
366         cgu = ingenic_cgu_new(x1000_cgu_clocks,
367                               ARRAY_SIZE(x1000_cgu_clocks), np);
368         if (!cgu) {
369                 pr_err("%s: failed to initialise CGU\n", __func__);
370                 return;
371         }
372
373         retval = ingenic_cgu_register_clocks(cgu);
374         if (retval) {
375                 pr_err("%s: failed to register CGU Clocks\n", __func__);
376                 return;
377         }
378
379         ingenic_cgu_register_syscore_ops(cgu);
380 }
381 /*
382  * CGU has some children devices, this is useful for probing children devices
383  * in the case where the device node is compatible with "simple-mfd".
384  */
385 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);