1 // SPDX-License-Identifier: GPL-2.0
4 * Copyright (c) 2019 周琰杰 (Zhou Yanjie) <zhouyanjie@wanyeetech.com>
7 #include <linux/clk-provider.h>
8 #include <linux/delay.h>
12 #include <dt-bindings/clock/x1000-cgu.h>
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
43 /* bits within the OPCR register */
44 #define OPCR_SPENDN0 BIT(7)
45 #define OPCR_SPENDN1 BIT(6)
47 /* bits within the USBPCR register */
48 #define USBPCR_SIDDQ BIT(21)
49 #define USBPCR_OTG_DISABLE BIT(20)
51 /* bits within the USBPCR1 register */
52 #define USBPCR1_REFCLKSEL_SHIFT 26
53 #define USBPCR1_REFCLKSEL_MASK (0x3 << USBPCR1_REFCLKSEL_SHIFT)
54 #define USBPCR1_REFCLKSEL_CORE (0x2 << USBPCR1_REFCLKSEL_SHIFT)
55 #define USBPCR1_REFCLKDIV_SHIFT 24
56 #define USBPCR1_REFCLKDIV_MASK (0x3 << USBPCR1_REFCLKDIV_SHIFT)
57 #define USBPCR1_REFCLKDIV_48 (0x2 << USBPCR1_REFCLKDIV_SHIFT)
58 #define USBPCR1_REFCLKDIV_24 (0x1 << USBPCR1_REFCLKDIV_SHIFT)
59 #define USBPCR1_REFCLKDIV_12 (0x0 << USBPCR1_REFCLKDIV_SHIFT)
61 static struct ingenic_cgu
*cgu
;
63 static unsigned long x1000_otg_phy_recalc_rate(struct clk_hw
*hw
,
64 unsigned long parent_rate
)
69 usbpcr1
= readl(cgu
->base
+ CGU_REG_USBPCR1
);
70 refclk_div
= usbpcr1
& USBPCR1_REFCLKDIV_MASK
;
73 case USBPCR1_REFCLKDIV_12
:
76 case USBPCR1_REFCLKDIV_24
:
79 case USBPCR1_REFCLKDIV_48
:
86 static long x1000_otg_phy_round_rate(struct clk_hw
*hw
, unsigned long req_rate
,
87 unsigned long *parent_rate
)
89 if (req_rate
< 18000000)
92 if (req_rate
< 36000000)
98 static int x1000_otg_phy_set_rate(struct clk_hw
*hw
, unsigned long req_rate
,
99 unsigned long parent_rate
)
102 u32 usbpcr1
, div_bits
;
106 div_bits
= USBPCR1_REFCLKDIV_12
;
110 div_bits
= USBPCR1_REFCLKDIV_24
;
114 div_bits
= USBPCR1_REFCLKDIV_48
;
121 spin_lock_irqsave(&cgu
->lock
, flags
);
123 usbpcr1
= readl(cgu
->base
+ CGU_REG_USBPCR1
);
124 usbpcr1
&= ~USBPCR1_REFCLKDIV_MASK
;
126 writel(usbpcr1
, cgu
->base
+ CGU_REG_USBPCR1
);
128 spin_unlock_irqrestore(&cgu
->lock
, flags
);
132 static int x1000_usb_phy_enable(struct clk_hw
*hw
)
134 void __iomem
*reg_opcr
= cgu
->base
+ CGU_REG_OPCR
;
135 void __iomem
*reg_usbpcr
= cgu
->base
+ CGU_REG_USBPCR
;
137 writel(readl(reg_opcr
) | OPCR_SPENDN0
, reg_opcr
);
138 writel(readl(reg_usbpcr
) & ~USBPCR_OTG_DISABLE
& ~USBPCR_SIDDQ
, reg_usbpcr
);
142 static void x1000_usb_phy_disable(struct clk_hw
*hw
)
144 void __iomem
*reg_opcr
= cgu
->base
+ CGU_REG_OPCR
;
145 void __iomem
*reg_usbpcr
= cgu
->base
+ CGU_REG_USBPCR
;
147 writel(readl(reg_opcr
) & ~OPCR_SPENDN0
, reg_opcr
);
148 writel(readl(reg_usbpcr
) | USBPCR_OTG_DISABLE
| USBPCR_SIDDQ
, reg_usbpcr
);
151 static int x1000_usb_phy_is_enabled(struct clk_hw
*hw
)
153 void __iomem
*reg_opcr
= cgu
->base
+ CGU_REG_OPCR
;
154 void __iomem
*reg_usbpcr
= cgu
->base
+ CGU_REG_USBPCR
;
156 return (readl(reg_opcr
) & OPCR_SPENDN0
) &&
157 !(readl(reg_usbpcr
) & USBPCR_SIDDQ
) &&
158 !(readl(reg_usbpcr
) & USBPCR_OTG_DISABLE
);
161 static const struct clk_ops x1000_otg_phy_ops
= {
162 .recalc_rate
= x1000_otg_phy_recalc_rate
,
163 .round_rate
= x1000_otg_phy_round_rate
,
164 .set_rate
= x1000_otg_phy_set_rate
,
166 .enable
= x1000_usb_phy_enable
,
167 .disable
= x1000_usb_phy_disable
,
168 .is_enabled
= x1000_usb_phy_is_enabled
,
171 static const s8 pll_od_encoding
[8] = {
172 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
175 static const struct ingenic_cgu_clk_info x1000_cgu_clocks
[] = {
177 /* External clocks */
179 [X1000_CLK_EXCLK
] = { "ext", CGU_CLK_EXT
},
180 [X1000_CLK_RTCLK
] = { "rtc", CGU_CLK_EXT
},
186 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
189 .rate_multiplier
= 1,
199 .od_encoding
= pll_od_encoding
,
200 .bypass_reg
= CGU_REG_APLL
,
209 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
212 .rate_multiplier
= 1,
222 .od_encoding
= pll_od_encoding
,
223 .bypass_reg
= CGU_REG_MPLL
,
230 /* Custom (SoC-specific) OTG PHY */
232 [X1000_CLK_OTGPHY
] = {
233 "otg_phy", CGU_CLK_CUSTOM
,
234 .parents
= { -1, -1, X1000_CLK_EXCLK
, -1 },
235 .custom
= { &x1000_otg_phy_ops
},
238 /* Muxes & dividers */
240 [X1000_CLK_SCLKA
] = {
241 "sclk_a", CGU_CLK_MUX
,
242 .parents
= { -1, X1000_CLK_EXCLK
, X1000_CLK_APLL
, -1 },
243 .mux
= { CGU_REG_CPCCR
, 30, 2 },
246 [X1000_CLK_CPUMUX
] = {
247 "cpu_mux", CGU_CLK_MUX
,
248 .parents
= { -1, X1000_CLK_SCLKA
, X1000_CLK_MPLL
, -1 },
249 .mux
= { CGU_REG_CPCCR
, 28, 2 },
253 "cpu", CGU_CLK_DIV
| CGU_CLK_GATE
,
254 .parents
= { X1000_CLK_CPUMUX
, -1, -1, -1 },
255 .div
= { CGU_REG_CPCCR
, 0, 1, 4, 22, -1, -1 },
256 .gate
= { CGU_REG_CLKGR
, 30 },
259 [X1000_CLK_L2CACHE
] = {
260 "l2cache", CGU_CLK_DIV
,
261 .parents
= { X1000_CLK_CPUMUX
, -1, -1, -1 },
262 .div
= { CGU_REG_CPCCR
, 4, 1, 4, 22, -1, -1 },
266 "ahb0", CGU_CLK_MUX
| CGU_CLK_DIV
,
267 .parents
= { -1, X1000_CLK_SCLKA
, X1000_CLK_MPLL
, -1 },
268 .mux
= { CGU_REG_CPCCR
, 26, 2 },
269 .div
= { CGU_REG_CPCCR
, 8, 1, 4, 21, -1, -1 },
272 [X1000_CLK_AHB2PMUX
] = {
273 "ahb2_apb_mux", CGU_CLK_MUX
,
274 .parents
= { -1, X1000_CLK_SCLKA
, X1000_CLK_MPLL
, -1 },
275 .mux
= { CGU_REG_CPCCR
, 24, 2 },
280 .parents
= { X1000_CLK_AHB2PMUX
, -1, -1, -1 },
281 .div
= { CGU_REG_CPCCR
, 12, 1, 4, 20, -1, -1 },
285 "pclk", CGU_CLK_DIV
| CGU_CLK_GATE
,
286 .parents
= { X1000_CLK_AHB2PMUX
, -1, -1, -1 },
287 .div
= { CGU_REG_CPCCR
, 16, 1, 4, 20, -1, -1 },
288 .gate
= { CGU_REG_CLKGR
, 28 },
292 "ddr", CGU_CLK_MUX
| CGU_CLK_DIV
| CGU_CLK_GATE
,
293 .parents
= { -1, X1000_CLK_SCLKA
, X1000_CLK_MPLL
, -1 },
294 .mux
= { CGU_REG_DDRCDR
, 30, 2 },
295 .div
= { CGU_REG_DDRCDR
, 0, 1, 4, 29, 28, 27 },
296 .gate
= { CGU_REG_CLKGR
, 31 },
300 "mac", CGU_CLK_MUX
| CGU_CLK_DIV
| CGU_CLK_GATE
,
301 .parents
= { X1000_CLK_SCLKA
, X1000_CLK_MPLL
},
302 .mux
= { CGU_REG_MACCDR
, 31, 1 },
303 .div
= { CGU_REG_MACCDR
, 0, 1, 8, 29, 28, 27 },
304 .gate
= { CGU_REG_CLKGR
, 25 },
308 "lcd", CGU_CLK_MUX
| CGU_CLK_DIV
| CGU_CLK_GATE
,
309 .parents
= { X1000_CLK_SCLKA
, X1000_CLK_MPLL
},
310 .mux
= { CGU_REG_LPCDR
, 31, 1 },
311 .div
= { CGU_REG_LPCDR
, 0, 1, 8, 28, 27, 26 },
312 .gate
= { CGU_REG_CLKGR
, 23 },
315 [X1000_CLK_MSCMUX
] = {
316 "msc_mux", CGU_CLK_MUX
,
317 .parents
= { X1000_CLK_SCLKA
, X1000_CLK_MPLL
},
318 .mux
= { CGU_REG_MSC0CDR
, 31, 1 },
322 "msc0", CGU_CLK_DIV
| CGU_CLK_GATE
,
323 .parents
= { X1000_CLK_MSCMUX
, -1, -1, -1 },
324 .div
= { CGU_REG_MSC0CDR
, 0, 2, 8, 29, 28, 27 },
325 .gate
= { CGU_REG_CLKGR
, 4 },
329 "msc1", CGU_CLK_DIV
| CGU_CLK_GATE
,
330 .parents
= { X1000_CLK_MSCMUX
, -1, -1, -1 },
331 .div
= { CGU_REG_MSC1CDR
, 0, 2, 8, 29, 28, 27 },
332 .gate
= { CGU_REG_CLKGR
, 5 },
336 "otg", CGU_CLK_DIV
| CGU_CLK_GATE
| CGU_CLK_MUX
,
337 .parents
= { X1000_CLK_EXCLK
, -1,
338 X1000_CLK_APLL
, X1000_CLK_MPLL
},
339 .mux
= { CGU_REG_USBCDR
, 30, 2 },
340 .div
= { CGU_REG_USBCDR
, 0, 1, 8, 29, 28, 27 },
341 .gate
= { CGU_REG_CLKGR
, 3 },
344 [X1000_CLK_SSIPLL
] = {
345 "ssi_pll", CGU_CLK_MUX
| CGU_CLK_DIV
,
346 .parents
= { X1000_CLK_SCLKA
, X1000_CLK_MPLL
, -1, -1 },
347 .mux
= { CGU_REG_SSICDR
, 31, 1 },
348 .div
= { CGU_REG_SSICDR
, 0, 1, 8, 29, 28, 27 },
351 [X1000_CLK_SSIPLL_DIV2
] = {
352 "ssi_pll_div2", CGU_CLK_FIXDIV
,
353 .parents
= { X1000_CLK_SSIPLL
},
357 [X1000_CLK_SSIMUX
] = {
358 "ssi_mux", CGU_CLK_MUX
,
359 .parents
= { X1000_CLK_EXCLK
, X1000_CLK_SSIPLL_DIV2
, -1, -1 },
360 .mux
= { CGU_REG_SSICDR
, 30, 1 },
363 [X1000_CLK_EXCLK_DIV512
] = {
364 "exclk_div512", CGU_CLK_FIXDIV
,
365 .parents
= { X1000_CLK_EXCLK
},
370 "rtc_ercs", CGU_CLK_MUX
| CGU_CLK_GATE
,
371 .parents
= { X1000_CLK_EXCLK_DIV512
, X1000_CLK_RTCLK
},
372 .mux
= { CGU_REG_OPCR
, 2, 1},
373 .gate
= { CGU_REG_CLKGR
, 27 },
376 /* Gate-only clocks */
380 .parents
= { X1000_CLK_AHB2
, -1, -1, -1 },
381 .gate
= { CGU_REG_CLKGR
, 0 },
384 [X1000_CLK_EFUSE
] = {
385 "efuse", CGU_CLK_GATE
,
386 .parents
= { X1000_CLK_AHB2
, -1, -1, -1 },
387 .gate
= { CGU_REG_CLKGR
, 1 },
392 .parents
= { X1000_CLK_SSIPLL
, -1, -1, -1 },
393 .gate
= { CGU_REG_CLKGR
, 2 },
397 "i2c0", CGU_CLK_GATE
,
398 .parents
= { X1000_CLK_PCLK
, -1, -1, -1 },
399 .gate
= { CGU_REG_CLKGR
, 7 },
403 "i2c1", CGU_CLK_GATE
,
404 .parents
= { X1000_CLK_PCLK
, -1, -1, -1 },
405 .gate
= { CGU_REG_CLKGR
, 8 },
409 "i2c2", CGU_CLK_GATE
,
410 .parents
= { X1000_CLK_PCLK
, -1, -1, -1 },
411 .gate
= { CGU_REG_CLKGR
, 9 },
414 [X1000_CLK_UART0
] = {
415 "uart0", CGU_CLK_GATE
,
416 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
417 .gate
= { CGU_REG_CLKGR
, 14 },
420 [X1000_CLK_UART1
] = {
421 "uart1", CGU_CLK_GATE
,
422 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
423 .gate
= { CGU_REG_CLKGR
, 15 },
426 [X1000_CLK_UART2
] = {
427 "uart2", CGU_CLK_GATE
,
428 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
429 .gate
= { CGU_REG_CLKGR
, 16 },
434 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
435 .gate
= { CGU_REG_CLKGR
, 18 },
440 .parents
= { X1000_CLK_SSIMUX
, -1, -1, -1 },
441 .gate
= { CGU_REG_CLKGR
, 19 },
446 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
447 .gate
= { CGU_REG_CLKGR
, 20 },
451 "pdma", CGU_CLK_GATE
,
452 .parents
= { X1000_CLK_EXCLK
, -1, -1, -1 },
453 .gate
= { CGU_REG_CLKGR
, 21 },
457 static void __init
x1000_cgu_init(struct device_node
*np
)
461 cgu
= ingenic_cgu_new(x1000_cgu_clocks
,
462 ARRAY_SIZE(x1000_cgu_clocks
), np
);
464 pr_err("%s: failed to initialise CGU\n", __func__
);
468 retval
= ingenic_cgu_register_clocks(cgu
);
470 pr_err("%s: failed to register CGU Clocks\n", __func__
);
474 ingenic_cgu_register_syscore_ops(cgu
);
477 * CGU has some children devices, this is useful for probing children devices
478 * in the case where the device node is compatible with "simple-mfd".
480 CLK_OF_DECLARE_DRIVER(x1000_cgu
, "ingenic,x1000-cgu", x1000_cgu_init
);