1
1
// SPDX-License-Identifier: GPL-2.0
2
2
/*
3
3
* X1000 SoC CGU driver
4
- * Copyright (c) 2019 Zhou Yanjie <zhouyanjie@zoho .com>
4
+ * Copyright (c) 2019 周琰杰 ( Zhou Yanjie) <zhouyanjie@wanyeetech .com>
5
5
*/
6
6
7
7
#include <linux/clk-provider.h>
8
8
#include <linux/delay.h>
9
+ #include <linux/io.h>
9
10
#include <linux/of.h>
10
11
11
12
#include <dt-bindings/clock/x1000-cgu.h>
20
21
#define CGU_REG_CLKGR 0x20
21
22
#define CGU_REG_OPCR 0x24
22
23
#define CGU_REG_DDRCDR 0x2c
24
+ #define CGU_REG_USBPCR 0x3c
25
+ #define CGU_REG_USBPCR1 0x48
26
+ #define CGU_REG_USBCDR 0x50
23
27
#define CGU_REG_MACCDR 0x54
24
28
#define CGU_REG_I2SCDR 0x60
25
29
#define CGU_REG_LPCDR 0x64
40
44
#define OPCR_SPENDN0 BIT(7)
41
45
#define OPCR_SPENDN1 BIT(6)
42
46
47
+ /* bits within the USBPCR register */
48
+ #define USBPCR_SIDDQ BIT(21)
49
+ #define USBPCR_OTG_DISABLE BIT(20)
50
+
43
51
static struct ingenic_cgu * cgu ;
44
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
+
45
88
static const s8 pll_od_encoding [8 ] = {
46
89
0x0 , 0x1 , -1 , 0x2 , -1 , -1 , -1 , 0x3 ,
47
90
};
@@ -101,6 +144,15 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
101
144
},
102
145
},
103
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
+
104
156
/* Muxes & dividers */
105
157
106
158
[X1000_CLK_SCLKA ] = {
@@ -116,9 +168,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
116
168
},
117
169
118
170
[X1000_CLK_CPU ] = {
119
- "cpu" , CGU_CLK_DIV ,
171
+ "cpu" , CGU_CLK_DIV | CGU_CLK_GATE ,
120
172
.parents = { X1000_CLK_CPUMUX , -1 , -1 , -1 },
121
173
.div = { CGU_REG_CPCCR , 0 , 1 , 4 , 22 , -1 , -1 },
174
+ .gate = { CGU_REG_CLKGR , 30 },
122
175
},
123
176
124
177
[X1000_CLK_L2CACHE ] = {
@@ -147,9 +200,10 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
147
200
},
148
201
149
202
[X1000_CLK_PCLK ] = {
150
- "pclk" , CGU_CLK_DIV ,
203
+ "pclk" , CGU_CLK_DIV | CGU_CLK_GATE ,
151
204
.parents = { X1000_CLK_AHB2PMUX , -1 , -1 , -1 },
152
205
.div = { CGU_REG_CPCCR , 16 , 1 , 4 , 20 , -1 , -1 },
206
+ .gate = { CGU_REG_CLKGR , 28 },
153
207
},
154
208
155
209
[X1000_CLK_DDR ] = {
@@ -162,12 +216,20 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
162
216
163
217
[X1000_CLK_MAC ] = {
164
218
"mac" , CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE ,
165
- .parents = { X1000_CLK_SCLKA , X1000_CLK_MPLL },
219
+ .parents = { X1000_CLK_SCLKA , X1000_CLK_MPLL },
166
220
.mux = { CGU_REG_MACCDR , 31 , 1 },
167
221
.div = { CGU_REG_MACCDR , 0 , 1 , 8 , 29 , 28 , 27 },
168
222
.gate = { CGU_REG_CLKGR , 25 },
169
223
},
170
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
+
171
233
[X1000_CLK_MSCMUX ] = {
172
234
"msc_mux" , CGU_CLK_MUX ,
173
235
.parents = { X1000_CLK_SCLKA , X1000_CLK_MPLL },
@@ -188,21 +250,48 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
188
250
.gate = { CGU_REG_CLKGR , 5 },
189
251
},
190
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
+
191
262
[X1000_CLK_SSIPLL ] = {
192
263
"ssi_pll" , CGU_CLK_MUX | CGU_CLK_DIV ,
193
264
.parents = { X1000_CLK_SCLKA , X1000_CLK_MPLL , -1 , -1 },
194
265
.mux = { CGU_REG_SSICDR , 31 , 1 },
195
266
.div = { CGU_REG_SSICDR , 0 , 1 , 8 , 29 , 28 , 27 },
196
267
},
197
268
269
+ [X1000_CLK_SSIPLL_DIV2 ] = {
270
+ "ssi_pll_div2" , CGU_CLK_FIXDIV ,
271
+ .parents = { X1000_CLK_SSIPLL },
272
+ .fixdiv = { 2 },
273
+ },
274
+
198
275
[X1000_CLK_SSIMUX ] = {
199
276
"ssi_mux" , CGU_CLK_MUX ,
200
- .parents = { X1000_CLK_EXCLK , X1000_CLK_SSIPLL , -1 , -1 },
277
+ .parents = { X1000_CLK_EXCLK , X1000_CLK_SSIPLL_DIV2 , -1 , -1 },
201
278
.mux = { CGU_REG_SSICDR , 30 , 1 },
202
279
},
203
280
204
281
/* Gate-only clocks */
205
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
+
206
295
[X1000_CLK_SFC ] = {
207
296
"sfc" , CGU_CLK_GATE ,
208
297
.parents = { X1000_CLK_SSIPLL , -1 , -1 , -1 },
@@ -245,12 +334,24 @@ static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
245
334
.gate = { CGU_REG_CLKGR , 16 },
246
335
},
247
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
+
248
343
[X1000_CLK_SSI ] = {
249
344
"ssi" , CGU_CLK_GATE ,
250
345
.parents = { X1000_CLK_SSIMUX , -1 , -1 , -1 },
251
346
.gate = { CGU_REG_CLKGR , 19 },
252
347
},
253
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
+
254
355
[X1000_CLK_PDMA ] = {
255
356
"pdma" , CGU_CLK_GATE ,
256
357
.parents = { X1000_CLK_EXCLK , -1 , -1 , -1 },
@@ -277,4 +378,8 @@ static void __init x1000_cgu_init(struct device_node *np)
277
378
278
379
ingenic_cgu_register_syscore_ops (cgu );
279
380
}
280
- CLK_OF_DECLARE (x1000_cgu , "ingenic,x1000-cgu" , x1000_cgu_init );
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 );
0 commit comments