Skip to content

Commit b9df399

Browse files
XBurstbebarino
authored andcommitted
clk: Ingenic: Add CGU driver for X1000.
Add support for the clocks provided by the CGU in the Ingenic X1000 SoC, making use of the cgu code to do the heavy lifting. Signed-off-by: Zhou Yanjie <[email protected]> Link: https://lkml.kernel.org/r/[email protected] Reviewed-by: Paul Cercueil <[email protected]> Signed-off-by: Stephen Boyd <[email protected]>
1 parent 0b24748 commit b9df399

File tree

3 files changed

+285
-0
lines changed

3 files changed

+285
-0
lines changed

drivers/clk/ingenic/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,16 @@ config INGENIC_CGU_JZ4780
4545

4646
If building for a JZ4780 SoC, you want to say Y here.
4747

48+
config INGENIC_CGU_X1000
49+
bool "Ingenic X1000 CGU driver"
50+
default MACH_X1000
51+
select INGENIC_CGU_COMMON
52+
help
53+
Support the clocks provided by the CGU hardware on Ingenic X1000
54+
and compatible SoCs.
55+
56+
If building for a X1000 SoC, you want to say Y here.
57+
4858
config INGENIC_TCU_CLK
4959
bool "Ingenic JZ47xx TCU clocks driver"
5060
default MACH_INGENIC

drivers/clk/ingenic/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ obj-$(CONFIG_INGENIC_CGU_JZ4740) += jz4740-cgu.o
44
obj-$(CONFIG_INGENIC_CGU_JZ4725B) += jz4725b-cgu.o
55
obj-$(CONFIG_INGENIC_CGU_JZ4770) += jz4770-cgu.o
66
obj-$(CONFIG_INGENIC_CGU_JZ4780) += jz4780-cgu.o
7+
obj-$(CONFIG_INGENIC_CGU_X1000) += x1000-cgu.o
78
obj-$(CONFIG_INGENIC_TCU_CLK) += tcu.o

drivers/clk/ingenic/x1000-cgu.c

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/*
3+
* X1000 SoC CGU driver
4+
* Copyright (c) 2019 Zhou Yanjie <[email protected]>
5+
*/
6+
7+
#include <linux/clk-provider.h>
8+
#include <linux/delay.h>
9+
#include <linux/of.h>
10+
#include <dt-bindings/clock/x1000-cgu.h>
11+
#include "cgu.h"
12+
#include "pm.h"
13+
14+
/* CGU register offsets */
15+
#define CGU_REG_CPCCR 0x00
16+
#define CGU_REG_APLL 0x10
17+
#define CGU_REG_MPLL 0x14
18+
#define CGU_REG_CLKGR 0x20
19+
#define CGU_REG_OPCR 0x24
20+
#define CGU_REG_DDRCDR 0x2c
21+
#define CGU_REG_MACCDR 0x54
22+
#define CGU_REG_I2SCDR 0x60
23+
#define CGU_REG_LPCDR 0x64
24+
#define CGU_REG_MSC0CDR 0x68
25+
#define CGU_REG_I2SCDR1 0x70
26+
#define CGU_REG_SSICDR 0x74
27+
#define CGU_REG_CIMCDR 0x7c
28+
#define CGU_REG_PCMCDR 0x84
29+
#define CGU_REG_MSC1CDR 0xa4
30+
#define CGU_REG_CMP_INTR 0xb0
31+
#define CGU_REG_CMP_INTRE 0xb4
32+
#define CGU_REG_DRCG 0xd0
33+
#define CGU_REG_CPCSR 0xd4
34+
#define CGU_REG_PCMCDR1 0xe0
35+
#define CGU_REG_MACPHYC 0xe8
36+
37+
/* bits within the OPCR register */
38+
#define OPCR_SPENDN0 BIT(7)
39+
#define OPCR_SPENDN1 BIT(6)
40+
41+
static struct ingenic_cgu *cgu;
42+
43+
static const s8 pll_od_encoding[8] = {
44+
0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
45+
};
46+
47+
static const struct ingenic_cgu_clk_info x1000_cgu_clocks[] = {
48+
49+
/* External clocks */
50+
51+
[X1000_CLK_EXCLK] = { "ext", CGU_CLK_EXT },
52+
[X1000_CLK_RTCLK] = { "rtc", CGU_CLK_EXT },
53+
54+
/* PLLs */
55+
56+
[X1000_CLK_APLL] = {
57+
"apll", CGU_CLK_PLL,
58+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
59+
.pll = {
60+
.reg = CGU_REG_APLL,
61+
.m_shift = 24,
62+
.m_bits = 7,
63+
.m_offset = 1,
64+
.n_shift = 18,
65+
.n_bits = 5,
66+
.n_offset = 1,
67+
.od_shift = 16,
68+
.od_bits = 2,
69+
.od_max = 8,
70+
.od_encoding = pll_od_encoding,
71+
.bypass_bit = 9,
72+
.enable_bit = 8,
73+
.stable_bit = 10,
74+
},
75+
},
76+
77+
[X1000_CLK_MPLL] = {
78+
"mpll", CGU_CLK_PLL,
79+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
80+
.pll = {
81+
.reg = CGU_REG_MPLL,
82+
.m_shift = 24,
83+
.m_bits = 7,
84+
.m_offset = 1,
85+
.n_shift = 18,
86+
.n_bits = 5,
87+
.n_offset = 1,
88+
.od_shift = 16,
89+
.od_bits = 2,
90+
.od_max = 8,
91+
.od_encoding = pll_od_encoding,
92+
.bypass_bit = 6,
93+
.enable_bit = 7,
94+
.stable_bit = 0,
95+
},
96+
},
97+
98+
/* Muxes & dividers */
99+
100+
[X1000_CLK_SCLKA] = {
101+
"sclk_a", CGU_CLK_MUX,
102+
.parents = { -1, X1000_CLK_EXCLK, X1000_CLK_APLL, -1 },
103+
.mux = { CGU_REG_CPCCR, 30, 2 },
104+
},
105+
106+
[X1000_CLK_CPUMUX] = {
107+
"cpu_mux", CGU_CLK_MUX,
108+
.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
109+
.mux = { CGU_REG_CPCCR, 28, 2 },
110+
},
111+
112+
[X1000_CLK_CPU] = {
113+
"cpu", CGU_CLK_DIV,
114+
.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
115+
.div = { CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1 },
116+
},
117+
118+
[X1000_CLK_L2CACHE] = {
119+
"l2cache", CGU_CLK_DIV,
120+
.parents = { X1000_CLK_CPUMUX, -1, -1, -1 },
121+
.div = { CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1 },
122+
},
123+
124+
[X1000_CLK_AHB0] = {
125+
"ahb0", CGU_CLK_MUX | CGU_CLK_DIV,
126+
.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
127+
.mux = { CGU_REG_CPCCR, 26, 2 },
128+
.div = { CGU_REG_CPCCR, 8, 1, 4, 21, -1, -1 },
129+
},
130+
131+
[X1000_CLK_AHB2PMUX] = {
132+
"ahb2_apb_mux", CGU_CLK_MUX,
133+
.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
134+
.mux = { CGU_REG_CPCCR, 24, 2 },
135+
},
136+
137+
[X1000_CLK_AHB2] = {
138+
"ahb2", CGU_CLK_DIV,
139+
.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
140+
.div = { CGU_REG_CPCCR, 12, 1, 4, 20, -1, -1 },
141+
},
142+
143+
[X1000_CLK_PCLK] = {
144+
"pclk", CGU_CLK_DIV,
145+
.parents = { X1000_CLK_AHB2PMUX, -1, -1, -1 },
146+
.div = { CGU_REG_CPCCR, 16, 1, 4, 20, -1, -1 },
147+
},
148+
149+
[X1000_CLK_DDR] = {
150+
"ddr", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
151+
.parents = { -1, X1000_CLK_SCLKA, X1000_CLK_MPLL, -1 },
152+
.mux = { CGU_REG_DDRCDR, 30, 2 },
153+
.div = { CGU_REG_DDRCDR, 0, 1, 4, 29, 28, 27 },
154+
.gate = { CGU_REG_CLKGR, 31 },
155+
},
156+
157+
[X1000_CLK_MAC] = {
158+
"mac", CGU_CLK_MUX | CGU_CLK_DIV | CGU_CLK_GATE,
159+
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
160+
.mux = { CGU_REG_MACCDR, 31, 1 },
161+
.div = { CGU_REG_MACCDR, 0, 1, 8, 29, 28, 27 },
162+
.gate = { CGU_REG_CLKGR, 25 },
163+
},
164+
165+
[X1000_CLK_MSCMUX] = {
166+
"msc_mux", CGU_CLK_MUX,
167+
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL},
168+
.mux = { CGU_REG_MSC0CDR, 31, 1 },
169+
},
170+
171+
[X1000_CLK_MSC0] = {
172+
"msc0", CGU_CLK_DIV | CGU_CLK_GATE,
173+
.parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
174+
.div = { CGU_REG_MSC0CDR, 0, 2, 8, 29, 28, 27 },
175+
.gate = { CGU_REG_CLKGR, 4 },
176+
},
177+
178+
[X1000_CLK_MSC1] = {
179+
"msc1", CGU_CLK_DIV | CGU_CLK_GATE,
180+
.parents = { X1000_CLK_MSCMUX, -1, -1, -1 },
181+
.div = { CGU_REG_MSC1CDR, 0, 2, 8, 29, 28, 27 },
182+
.gate = { CGU_REG_CLKGR, 5 },
183+
},
184+
185+
[X1000_CLK_SSIPLL] = {
186+
"ssi_pll", CGU_CLK_MUX | CGU_CLK_DIV,
187+
.parents = { X1000_CLK_SCLKA, X1000_CLK_MPLL, -1, -1 },
188+
.mux = { CGU_REG_SSICDR, 31, 1 },
189+
.div = { CGU_REG_SSICDR, 0, 1, 8, 29, 28, 27 },
190+
},
191+
192+
[X1000_CLK_SSIMUX] = {
193+
"ssi_mux", CGU_CLK_MUX,
194+
.parents = { X1000_CLK_EXCLK, X1000_CLK_SSIPLL, -1, -1 },
195+
.mux = { CGU_REG_SSICDR, 30, 1 },
196+
},
197+
198+
/* Gate-only clocks */
199+
200+
[X1000_CLK_SFC] = {
201+
"sfc", CGU_CLK_GATE,
202+
.parents = { X1000_CLK_SSIPLL, -1, -1, -1 },
203+
.gate = { CGU_REG_CLKGR, 2 },
204+
},
205+
206+
[X1000_CLK_I2C0] = {
207+
"i2c0", CGU_CLK_GATE,
208+
.parents = { X1000_CLK_PCLK, -1, -1, -1 },
209+
.gate = { CGU_REG_CLKGR, 7 },
210+
},
211+
212+
[X1000_CLK_I2C1] = {
213+
"i2c1", CGU_CLK_GATE,
214+
.parents = { X1000_CLK_PCLK, -1, -1, -1 },
215+
.gate = { CGU_REG_CLKGR, 8 },
216+
},
217+
218+
[X1000_CLK_I2C2] = {
219+
"i2c2", CGU_CLK_GATE,
220+
.parents = { X1000_CLK_PCLK, -1, -1, -1 },
221+
.gate = { CGU_REG_CLKGR, 9 },
222+
},
223+
224+
[X1000_CLK_UART0] = {
225+
"uart0", CGU_CLK_GATE,
226+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
227+
.gate = { CGU_REG_CLKGR, 14 },
228+
},
229+
230+
[X1000_CLK_UART1] = {
231+
"uart1", CGU_CLK_GATE,
232+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
233+
.gate = { CGU_REG_CLKGR, 15 },
234+
},
235+
236+
[X1000_CLK_UART2] = {
237+
"uart2", CGU_CLK_GATE,
238+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
239+
.gate = { CGU_REG_CLKGR, 16 },
240+
},
241+
242+
[X1000_CLK_SSI] = {
243+
"ssi", CGU_CLK_GATE,
244+
.parents = { X1000_CLK_SSIMUX, -1, -1, -1 },
245+
.gate = { CGU_REG_CLKGR, 19 },
246+
},
247+
248+
[X1000_CLK_PDMA] = {
249+
"pdma", CGU_CLK_GATE,
250+
.parents = { X1000_CLK_EXCLK, -1, -1, -1 },
251+
.gate = { CGU_REG_CLKGR, 21 },
252+
},
253+
};
254+
255+
static void __init x1000_cgu_init(struct device_node *np)
256+
{
257+
int retval;
258+
259+
cgu = ingenic_cgu_new(x1000_cgu_clocks,
260+
ARRAY_SIZE(x1000_cgu_clocks), np);
261+
if (!cgu) {
262+
pr_err("%s: failed to initialise CGU\n", __func__);
263+
return;
264+
}
265+
266+
retval = ingenic_cgu_register_clocks(cgu);
267+
if (retval) {
268+
pr_err("%s: failed to register CGU Clocks\n", __func__);
269+
return;
270+
}
271+
272+
ingenic_cgu_register_syscore_ops(cgu);
273+
}
274+
CLK_OF_DECLARE(x1000_cgu, "ingenic,x1000-cgu", x1000_cgu_init);

0 commit comments

Comments
 (0)