1bdbfc029SPaul Cercueil // SPDX-License-Identifier: GPL-2.0
2bdbfc029SPaul Cercueil /*
3bdbfc029SPaul Cercueil * JZ4760 SoC CGU driver
4bdbfc029SPaul Cercueil * Copyright 2018, Paul Cercueil <paul@crapouillou.net>
5bdbfc029SPaul Cercueil */
6bdbfc029SPaul Cercueil
7bdbfc029SPaul Cercueil #include <linux/bitops.h>
8bdbfc029SPaul Cercueil #include <linux/clk-provider.h>
9bdbfc029SPaul Cercueil #include <linux/delay.h>
10bdbfc029SPaul Cercueil #include <linux/io.h>
11bdbfc029SPaul Cercueil #include <linux/of.h>
12bdbfc029SPaul Cercueil
13bdbfc029SPaul Cercueil #include <linux/clk.h>
14bdbfc029SPaul Cercueil
15c4a11bf4SPaul Cercueil #include <dt-bindings/clock/ingenic,jz4760-cgu.h>
16bdbfc029SPaul Cercueil
17bdbfc029SPaul Cercueil #include "cgu.h"
18bdbfc029SPaul Cercueil #include "pm.h"
19bdbfc029SPaul Cercueil
20bdbfc029SPaul Cercueil #define MHZ (1000 * 1000)
21bdbfc029SPaul Cercueil
22bdbfc029SPaul Cercueil /*
23bdbfc029SPaul Cercueil * CPM registers offset address definition
24bdbfc029SPaul Cercueil */
25bdbfc029SPaul Cercueil #define CGU_REG_CPCCR 0x00
26bdbfc029SPaul Cercueil #define CGU_REG_LCR 0x04
27bdbfc029SPaul Cercueil #define CGU_REG_CPPCR0 0x10
28bdbfc029SPaul Cercueil #define CGU_REG_CLKGR0 0x20
29bdbfc029SPaul Cercueil #define CGU_REG_OPCR 0x24
30bdbfc029SPaul Cercueil #define CGU_REG_CLKGR1 0x28
31bdbfc029SPaul Cercueil #define CGU_REG_CPPCR1 0x30
32bdbfc029SPaul Cercueil #define CGU_REG_USBPCR 0x3c
33bdbfc029SPaul Cercueil #define CGU_REG_USBCDR 0x50
34bdbfc029SPaul Cercueil #define CGU_REG_I2SCDR 0x60
35bdbfc029SPaul Cercueil #define CGU_REG_LPCDR 0x64
36bdbfc029SPaul Cercueil #define CGU_REG_MSCCDR 0x68
37bdbfc029SPaul Cercueil #define CGU_REG_UHCCDR 0x6c
38bdbfc029SPaul Cercueil #define CGU_REG_SSICDR 0x74
39bdbfc029SPaul Cercueil #define CGU_REG_CIMCDR 0x7c
40bdbfc029SPaul Cercueil #define CGU_REG_GPSCDR 0x80
41bdbfc029SPaul Cercueil #define CGU_REG_PCMCDR 0x84
42bdbfc029SPaul Cercueil #define CGU_REG_GPUCDR 0x88
43bdbfc029SPaul Cercueil
44bdbfc029SPaul Cercueil static const s8 pll_od_encoding[8] = {
45bdbfc029SPaul Cercueil 0x0, 0x1, -1, 0x2, -1, -1, -1, 0x3,
46bdbfc029SPaul Cercueil };
47bdbfc029SPaul Cercueil
48bdbfc029SPaul Cercueil static const u8 jz4760_cgu_cpccr_div_table[] = {
49bdbfc029SPaul Cercueil 1, 2, 3, 4, 6, 8,
50bdbfc029SPaul Cercueil };
51bdbfc029SPaul Cercueil
52bdbfc029SPaul Cercueil static const u8 jz4760_cgu_pll_half_div_table[] = {
53bdbfc029SPaul Cercueil 2, 1,
54bdbfc029SPaul Cercueil };
55bdbfc029SPaul Cercueil
56bdbfc029SPaul Cercueil static void
jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info * pll_info,unsigned long rate,unsigned long parent_rate,unsigned int * pm,unsigned int * pn,unsigned int * pod)57bdbfc029SPaul Cercueil jz4760_cgu_calc_m_n_od(const struct ingenic_cgu_pll_info *pll_info,
58bdbfc029SPaul Cercueil unsigned long rate, unsigned long parent_rate,
59bdbfc029SPaul Cercueil unsigned int *pm, unsigned int *pn, unsigned int *pod)
60bdbfc029SPaul Cercueil {
61*ecfb9f40SPaul Cercueil unsigned int m, n, od, m_max = (1 << pll_info->m_bits) - 1;
62bdbfc029SPaul Cercueil
63bdbfc029SPaul Cercueil /* The frequency after the N divider must be between 1 and 50 MHz. */
64bdbfc029SPaul Cercueil n = parent_rate / (1 * MHZ);
65bdbfc029SPaul Cercueil
66bdbfc029SPaul Cercueil /* The N divider must be >= 2. */
67bdbfc029SPaul Cercueil n = clamp_val(n, 2, 1 << pll_info->n_bits);
68bdbfc029SPaul Cercueil
69*ecfb9f40SPaul Cercueil rate /= MHZ;
70*ecfb9f40SPaul Cercueil parent_rate /= MHZ;
71bdbfc029SPaul Cercueil
72*ecfb9f40SPaul Cercueil for (m = m_max; m >= m_max && n >= 2; n--) {
73*ecfb9f40SPaul Cercueil m = rate * n / parent_rate;
74*ecfb9f40SPaul Cercueil od = m & 1;
75*ecfb9f40SPaul Cercueil m <<= od;
76bdbfc029SPaul Cercueil }
77bdbfc029SPaul Cercueil
78bdbfc029SPaul Cercueil *pm = m;
79*ecfb9f40SPaul Cercueil *pn = n + 1;
80bdbfc029SPaul Cercueil *pod = 1 << od;
81bdbfc029SPaul Cercueil }
82bdbfc029SPaul Cercueil
83bdbfc029SPaul Cercueil static const struct ingenic_cgu_clk_info jz4760_cgu_clocks[] = {
84bdbfc029SPaul Cercueil
85bdbfc029SPaul Cercueil /* External clocks */
86bdbfc029SPaul Cercueil
87bdbfc029SPaul Cercueil [JZ4760_CLK_EXT] = { "ext", CGU_CLK_EXT },
88bdbfc029SPaul Cercueil [JZ4760_CLK_OSC32K] = { "osc32k", CGU_CLK_EXT },
89bdbfc029SPaul Cercueil
90bdbfc029SPaul Cercueil /* PLLs */
91bdbfc029SPaul Cercueil
92bdbfc029SPaul Cercueil [JZ4760_CLK_PLL0] = {
93bdbfc029SPaul Cercueil "pll0", CGU_CLK_PLL,
94bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT },
95bdbfc029SPaul Cercueil .pll = {
96bdbfc029SPaul Cercueil .reg = CGU_REG_CPPCR0,
97bdbfc029SPaul Cercueil .rate_multiplier = 1,
98bdbfc029SPaul Cercueil .m_shift = 23,
99bdbfc029SPaul Cercueil .m_bits = 8,
100bdbfc029SPaul Cercueil .m_offset = 0,
101bdbfc029SPaul Cercueil .n_shift = 18,
102bdbfc029SPaul Cercueil .n_bits = 4,
103bdbfc029SPaul Cercueil .n_offset = 0,
104bdbfc029SPaul Cercueil .od_shift = 16,
105bdbfc029SPaul Cercueil .od_bits = 2,
106bdbfc029SPaul Cercueil .od_max = 8,
107bdbfc029SPaul Cercueil .od_encoding = pll_od_encoding,
108bdbfc029SPaul Cercueil .bypass_reg = CGU_REG_CPPCR0,
109bdbfc029SPaul Cercueil .bypass_bit = 9,
110bdbfc029SPaul Cercueil .enable_bit = 8,
111bdbfc029SPaul Cercueil .stable_bit = 10,
112bdbfc029SPaul Cercueil .calc_m_n_od = jz4760_cgu_calc_m_n_od,
113bdbfc029SPaul Cercueil },
114bdbfc029SPaul Cercueil },
115bdbfc029SPaul Cercueil
116bdbfc029SPaul Cercueil [JZ4760_CLK_PLL1] = {
117bdbfc029SPaul Cercueil /* TODO: PLL1 can depend on PLL0 */
118bdbfc029SPaul Cercueil "pll1", CGU_CLK_PLL,
119bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT },
120bdbfc029SPaul Cercueil .pll = {
121bdbfc029SPaul Cercueil .reg = CGU_REG_CPPCR1,
122bdbfc029SPaul Cercueil .rate_multiplier = 1,
123bdbfc029SPaul Cercueil .m_shift = 23,
124bdbfc029SPaul Cercueil .m_bits = 8,
125bdbfc029SPaul Cercueil .m_offset = 0,
126bdbfc029SPaul Cercueil .n_shift = 18,
127bdbfc029SPaul Cercueil .n_bits = 4,
128bdbfc029SPaul Cercueil .n_offset = 0,
129bdbfc029SPaul Cercueil .od_shift = 16,
130bdbfc029SPaul Cercueil .od_bits = 2,
131bdbfc029SPaul Cercueil .od_max = 8,
132bdbfc029SPaul Cercueil .od_encoding = pll_od_encoding,
133bdbfc029SPaul Cercueil .bypass_bit = -1,
134bdbfc029SPaul Cercueil .enable_bit = 7,
135bdbfc029SPaul Cercueil .stable_bit = 6,
136bdbfc029SPaul Cercueil .calc_m_n_od = jz4760_cgu_calc_m_n_od,
137bdbfc029SPaul Cercueil },
138bdbfc029SPaul Cercueil },
139bdbfc029SPaul Cercueil
140bdbfc029SPaul Cercueil /* Main clocks */
141bdbfc029SPaul Cercueil
142bdbfc029SPaul Cercueil [JZ4760_CLK_CCLK] = {
143bdbfc029SPaul Cercueil "cclk", CGU_CLK_DIV,
144ca54d06fSAidan MacDonald /*
145ca54d06fSAidan MacDonald * Disabling the CPU clock or any parent clocks will hang the
146ca54d06fSAidan MacDonald * system; mark it critical.
147ca54d06fSAidan MacDonald */
148ca54d06fSAidan MacDonald .flags = CLK_IS_CRITICAL,
149bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
150bdbfc029SPaul Cercueil .div = {
151bdbfc029SPaul Cercueil CGU_REG_CPCCR, 0, 1, 4, 22, -1, -1, 0,
152bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
153bdbfc029SPaul Cercueil },
154bdbfc029SPaul Cercueil },
155bdbfc029SPaul Cercueil [JZ4760_CLK_HCLK] = {
156bdbfc029SPaul Cercueil "hclk", CGU_CLK_DIV,
157bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
158bdbfc029SPaul Cercueil .div = {
159bdbfc029SPaul Cercueil CGU_REG_CPCCR, 4, 1, 4, 22, -1, -1, 0,
160bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
161bdbfc029SPaul Cercueil },
162bdbfc029SPaul Cercueil },
163bdbfc029SPaul Cercueil [JZ4760_CLK_SCLK] = {
164bdbfc029SPaul Cercueil "sclk", CGU_CLK_DIV,
165bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
166bdbfc029SPaul Cercueil .div = {
167bdbfc029SPaul Cercueil CGU_REG_CPCCR, 24, 1, 4, 22, -1, -1, 0,
168bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
169bdbfc029SPaul Cercueil },
170bdbfc029SPaul Cercueil },
171bdbfc029SPaul Cercueil [JZ4760_CLK_H2CLK] = {
172bdbfc029SPaul Cercueil "h2clk", CGU_CLK_DIV,
173bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
174bdbfc029SPaul Cercueil .div = {
175bdbfc029SPaul Cercueil CGU_REG_CPCCR, 16, 1, 4, 22, -1, -1, 0,
176bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
177bdbfc029SPaul Cercueil },
178bdbfc029SPaul Cercueil },
179bdbfc029SPaul Cercueil [JZ4760_CLK_MCLK] = {
180bdbfc029SPaul Cercueil "mclk", CGU_CLK_DIV,
181ca54d06fSAidan MacDonald /*
182ca54d06fSAidan MacDonald * Disabling MCLK or its parents will render DRAM
183ca54d06fSAidan MacDonald * inaccessible; mark it critical.
184ca54d06fSAidan MacDonald */
185ca54d06fSAidan MacDonald .flags = CLK_IS_CRITICAL,
186bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
187bdbfc029SPaul Cercueil .div = {
188bdbfc029SPaul Cercueil CGU_REG_CPCCR, 12, 1, 4, 22, -1, -1, 0,
189bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
190bdbfc029SPaul Cercueil },
191bdbfc029SPaul Cercueil },
192bdbfc029SPaul Cercueil [JZ4760_CLK_PCLK] = {
193bdbfc029SPaul Cercueil "pclk", CGU_CLK_DIV,
194bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0, },
195bdbfc029SPaul Cercueil .div = {
196bdbfc029SPaul Cercueil CGU_REG_CPCCR, 8, 1, 4, 22, -1, -1, 0,
197bdbfc029SPaul Cercueil jz4760_cgu_cpccr_div_table,
198bdbfc029SPaul Cercueil },
199bdbfc029SPaul Cercueil },
200bdbfc029SPaul Cercueil
201bdbfc029SPaul Cercueil /* Divided clocks */
202bdbfc029SPaul Cercueil
203bdbfc029SPaul Cercueil [JZ4760_CLK_PLL0_HALF] = {
204bdbfc029SPaul Cercueil "pll0_half", CGU_CLK_DIV,
205bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0 },
206bdbfc029SPaul Cercueil .div = {
207bdbfc029SPaul Cercueil CGU_REG_CPCCR, 21, 1, 1, 22, -1, -1, 0,
208bdbfc029SPaul Cercueil jz4760_cgu_pll_half_div_table,
209bdbfc029SPaul Cercueil },
210bdbfc029SPaul Cercueil },
211bdbfc029SPaul Cercueil
212bdbfc029SPaul Cercueil /* Those divided clocks can connect to PLL0 or PLL1 */
213bdbfc029SPaul Cercueil
214bdbfc029SPaul Cercueil [JZ4760_CLK_UHC] = {
215bdbfc029SPaul Cercueil "uhc", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
216bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
217bdbfc029SPaul Cercueil .mux = { CGU_REG_UHCCDR, 31, 1 },
218bdbfc029SPaul Cercueil .div = { CGU_REG_UHCCDR, 0, 1, 4, -1, -1, -1 },
219bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 24 },
220bdbfc029SPaul Cercueil },
221bdbfc029SPaul Cercueil [JZ4760_CLK_GPU] = {
222bdbfc029SPaul Cercueil "gpu", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
223bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
224bdbfc029SPaul Cercueil .mux = { CGU_REG_GPUCDR, 31, 1 },
225bdbfc029SPaul Cercueil .div = { CGU_REG_GPUCDR, 0, 1, 3, -1, -1, -1 },
226bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR1, 9 },
227bdbfc029SPaul Cercueil },
228bdbfc029SPaul Cercueil [JZ4760_CLK_LPCLK_DIV] = {
229bdbfc029SPaul Cercueil "lpclk_div", CGU_CLK_DIV | CGU_CLK_MUX,
230bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
231bdbfc029SPaul Cercueil .mux = { CGU_REG_LPCDR, 29, 1 },
232bdbfc029SPaul Cercueil .div = { CGU_REG_LPCDR, 0, 1, 11, -1, -1, -1 },
233bdbfc029SPaul Cercueil },
234bdbfc029SPaul Cercueil [JZ4760_CLK_TVE] = {
235bdbfc029SPaul Cercueil "tve", CGU_CLK_GATE | CGU_CLK_MUX,
236bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_EXT, },
237bdbfc029SPaul Cercueil .mux = { CGU_REG_LPCDR, 31, 1 },
238bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 27 },
239bdbfc029SPaul Cercueil },
240bdbfc029SPaul Cercueil [JZ4760_CLK_LPCLK] = {
241bdbfc029SPaul Cercueil "lpclk", CGU_CLK_GATE | CGU_CLK_MUX,
242bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_LPCLK_DIV, JZ4760_CLK_TVE, },
243bdbfc029SPaul Cercueil .mux = { CGU_REG_LPCDR, 30, 1 },
244bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 28 },
245bdbfc029SPaul Cercueil },
246bdbfc029SPaul Cercueil [JZ4760_CLK_GPS] = {
247bdbfc029SPaul Cercueil "gps", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
248bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1, },
249bdbfc029SPaul Cercueil .mux = { CGU_REG_GPSCDR, 31, 1 },
250bdbfc029SPaul Cercueil .div = { CGU_REG_GPSCDR, 0, 1, 4, -1, -1, -1 },
251bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 22 },
252bdbfc029SPaul Cercueil },
253bdbfc029SPaul Cercueil
254bdbfc029SPaul Cercueil /* Those divided clocks can connect to EXT, PLL0 or PLL1 */
255bdbfc029SPaul Cercueil
256bdbfc029SPaul Cercueil [JZ4760_CLK_PCM] = {
257bdbfc029SPaul Cercueil "pcm", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
258bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, -1,
259bdbfc029SPaul Cercueil JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
260bdbfc029SPaul Cercueil .mux = { CGU_REG_PCMCDR, 30, 2 },
261bdbfc029SPaul Cercueil .div = { CGU_REG_PCMCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
262bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR1, 8 },
263bdbfc029SPaul Cercueil },
264bdbfc029SPaul Cercueil [JZ4760_CLK_I2S] = {
265bdbfc029SPaul Cercueil "i2s", CGU_CLK_DIV | CGU_CLK_MUX,
266bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, -1,
267bdbfc029SPaul Cercueil JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
268bdbfc029SPaul Cercueil .mux = { CGU_REG_I2SCDR, 30, 2 },
269bdbfc029SPaul Cercueil .div = { CGU_REG_I2SCDR, 0, 1, 9, -1, -1, -1, BIT(0) },
270bdbfc029SPaul Cercueil },
271bdbfc029SPaul Cercueil [JZ4760_CLK_OTG] = {
272bdbfc029SPaul Cercueil "usb", CGU_CLK_DIV | CGU_CLK_GATE | CGU_CLK_MUX,
273bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, -1,
274bdbfc029SPaul Cercueil JZ4760_CLK_PLL0_HALF, JZ4760_CLK_PLL1 },
275bdbfc029SPaul Cercueil .mux = { CGU_REG_USBCDR, 30, 2 },
276bdbfc029SPaul Cercueil .div = { CGU_REG_USBCDR, 0, 1, 8, -1, -1, -1 },
277bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 2 },
278bdbfc029SPaul Cercueil },
279bdbfc029SPaul Cercueil
280bdbfc029SPaul Cercueil /* Those divided clocks can connect to EXT or PLL0 */
281bdbfc029SPaul Cercueil [JZ4760_CLK_MMC_MUX] = {
282bdbfc029SPaul Cercueil "mmc_mux", CGU_CLK_MUX | CGU_CLK_DIV,
283bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
284bdbfc029SPaul Cercueil .mux = { CGU_REG_MSCCDR, 31, 1 },
285bdbfc029SPaul Cercueil .div = { CGU_REG_MSCCDR, 0, 1, 6, -1, -1, -1, BIT(0) },
286bdbfc029SPaul Cercueil },
287bdbfc029SPaul Cercueil [JZ4760_CLK_SSI_MUX] = {
288bdbfc029SPaul Cercueil "ssi_mux", CGU_CLK_DIV | CGU_CLK_MUX,
289bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, JZ4760_CLK_PLL0_HALF, },
290bdbfc029SPaul Cercueil .mux = { CGU_REG_SSICDR, 31, 1 },
291bdbfc029SPaul Cercueil .div = { CGU_REG_SSICDR, 0, 1, 6, -1, -1, -1, BIT(0) },
292bdbfc029SPaul Cercueil },
293bdbfc029SPaul Cercueil
294bdbfc029SPaul Cercueil /* These divided clock can connect to PLL0 only */
295bdbfc029SPaul Cercueil [JZ4760_CLK_CIM] = {
296bdbfc029SPaul Cercueil "cim", CGU_CLK_DIV | CGU_CLK_GATE,
297bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_PLL0_HALF },
298bdbfc029SPaul Cercueil .div = { CGU_REG_CIMCDR, 0, 1, 8, -1, -1, -1 },
299bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 26 },
300bdbfc029SPaul Cercueil },
301bdbfc029SPaul Cercueil
302bdbfc029SPaul Cercueil /* Gate-only clocks */
303bdbfc029SPaul Cercueil
304bdbfc029SPaul Cercueil [JZ4760_CLK_SSI0] = {
305bdbfc029SPaul Cercueil "ssi0", CGU_CLK_GATE,
306bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_SSI_MUX, },
307bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 4 },
308bdbfc029SPaul Cercueil },
309bdbfc029SPaul Cercueil [JZ4760_CLK_SSI1] = {
310bdbfc029SPaul Cercueil "ssi1", CGU_CLK_GATE,
311bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_SSI_MUX, },
312bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 19 },
313bdbfc029SPaul Cercueil },
314bdbfc029SPaul Cercueil [JZ4760_CLK_SSI2] = {
315bdbfc029SPaul Cercueil "ssi2", CGU_CLK_GATE,
316bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_SSI_MUX, },
317bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 20 },
318bdbfc029SPaul Cercueil },
319bdbfc029SPaul Cercueil [JZ4760_CLK_DMA] = {
320bdbfc029SPaul Cercueil "dma", CGU_CLK_GATE,
321bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_H2CLK, },
322bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 21 },
323bdbfc029SPaul Cercueil },
324b5bc83bbSPaul Cercueil [JZ4760_CLK_MDMA] = {
325b5bc83bbSPaul Cercueil "mdma", CGU_CLK_GATE,
326b5bc83bbSPaul Cercueil .parents = { JZ4760_CLK_HCLK, },
327b5bc83bbSPaul Cercueil .gate = { CGU_REG_CLKGR0, 25 },
328b5bc83bbSPaul Cercueil },
329b5bc83bbSPaul Cercueil [JZ4760_CLK_BDMA] = {
330b5bc83bbSPaul Cercueil "bdma", CGU_CLK_GATE,
331b5bc83bbSPaul Cercueil .parents = { JZ4760_CLK_HCLK, },
332b5bc83bbSPaul Cercueil .gate = { CGU_REG_CLKGR1, 0 },
333b5bc83bbSPaul Cercueil },
334bdbfc029SPaul Cercueil [JZ4760_CLK_I2C0] = {
335bdbfc029SPaul Cercueil "i2c0", CGU_CLK_GATE,
336bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
337bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 5 },
338bdbfc029SPaul Cercueil },
339bdbfc029SPaul Cercueil [JZ4760_CLK_I2C1] = {
340bdbfc029SPaul Cercueil "i2c1", CGU_CLK_GATE,
341bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
342bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 6 },
343bdbfc029SPaul Cercueil },
344bdbfc029SPaul Cercueil [JZ4760_CLK_UART0] = {
345bdbfc029SPaul Cercueil "uart0", CGU_CLK_GATE,
346bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
347bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 15 },
348bdbfc029SPaul Cercueil },
349bdbfc029SPaul Cercueil [JZ4760_CLK_UART1] = {
350bdbfc029SPaul Cercueil "uart1", CGU_CLK_GATE,
351bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
352bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 16 },
353bdbfc029SPaul Cercueil },
354bdbfc029SPaul Cercueil [JZ4760_CLK_UART2] = {
355bdbfc029SPaul Cercueil "uart2", CGU_CLK_GATE,
356bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
357bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 17 },
358bdbfc029SPaul Cercueil },
359bdbfc029SPaul Cercueil [JZ4760_CLK_UART3] = {
360bdbfc029SPaul Cercueil "uart3", CGU_CLK_GATE,
361bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
362bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 18 },
363bdbfc029SPaul Cercueil },
364bdbfc029SPaul Cercueil [JZ4760_CLK_IPU] = {
365bdbfc029SPaul Cercueil "ipu", CGU_CLK_GATE,
366bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_HCLK, },
367bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 29 },
368bdbfc029SPaul Cercueil },
369bdbfc029SPaul Cercueil [JZ4760_CLK_ADC] = {
370bdbfc029SPaul Cercueil "adc", CGU_CLK_GATE,
371bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
372bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 14 },
373bdbfc029SPaul Cercueil },
374bdbfc029SPaul Cercueil [JZ4760_CLK_AIC] = {
375bdbfc029SPaul Cercueil "aic", CGU_CLK_GATE,
376bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT, },
377bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 8 },
378bdbfc029SPaul Cercueil },
379bdbfc029SPaul Cercueil [JZ4760_CLK_VPU] = {
380bdbfc029SPaul Cercueil "vpu", CGU_CLK_GATE,
381bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_HCLK, },
382bdbfc029SPaul Cercueil .gate = { CGU_REG_LCR, 30, false, 150 },
383bdbfc029SPaul Cercueil },
384bdbfc029SPaul Cercueil [JZ4760_CLK_MMC0] = {
385bdbfc029SPaul Cercueil "mmc0", CGU_CLK_GATE,
386bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_MMC_MUX, },
387bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 3 },
388bdbfc029SPaul Cercueil },
389bdbfc029SPaul Cercueil [JZ4760_CLK_MMC1] = {
390bdbfc029SPaul Cercueil "mmc1", CGU_CLK_GATE,
391bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_MMC_MUX, },
392bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 11 },
393bdbfc029SPaul Cercueil },
394bdbfc029SPaul Cercueil [JZ4760_CLK_MMC2] = {
395bdbfc029SPaul Cercueil "mmc2", CGU_CLK_GATE,
396bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_MMC_MUX, },
397bdbfc029SPaul Cercueil .gate = { CGU_REG_CLKGR0, 12 },
398bdbfc029SPaul Cercueil },
399bdbfc029SPaul Cercueil [JZ4760_CLK_UHC_PHY] = {
400bdbfc029SPaul Cercueil "uhc_phy", CGU_CLK_GATE,
401bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_UHC, },
402bdbfc029SPaul Cercueil .gate = { CGU_REG_OPCR, 5 },
403bdbfc029SPaul Cercueil },
404bdbfc029SPaul Cercueil [JZ4760_CLK_OTG_PHY] = {
405bdbfc029SPaul Cercueil "usb_phy", CGU_CLK_GATE,
406bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_OTG },
407bdbfc029SPaul Cercueil .gate = { CGU_REG_OPCR, 7, true, 50 },
408bdbfc029SPaul Cercueil },
409bdbfc029SPaul Cercueil
410bdbfc029SPaul Cercueil /* Custom clocks */
411bdbfc029SPaul Cercueil [JZ4760_CLK_EXT512] = {
412bdbfc029SPaul Cercueil "ext/512", CGU_CLK_FIXDIV,
413bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT },
414bdbfc029SPaul Cercueil .fixdiv = { 512 },
415bdbfc029SPaul Cercueil },
416bdbfc029SPaul Cercueil [JZ4760_CLK_RTC] = {
417bdbfc029SPaul Cercueil "rtc", CGU_CLK_MUX,
418bdbfc029SPaul Cercueil .parents = { JZ4760_CLK_EXT512, JZ4760_CLK_OSC32K, },
419bdbfc029SPaul Cercueil .mux = { CGU_REG_OPCR, 2, 1},
420bdbfc029SPaul Cercueil },
421bdbfc029SPaul Cercueil };
422bdbfc029SPaul Cercueil
jz4760_cgu_init(struct device_node * np)423bdbfc029SPaul Cercueil static void __init jz4760_cgu_init(struct device_node *np)
424bdbfc029SPaul Cercueil {
425bdbfc029SPaul Cercueil struct ingenic_cgu *cgu;
426bdbfc029SPaul Cercueil int retval;
427bdbfc029SPaul Cercueil
428bdbfc029SPaul Cercueil cgu = ingenic_cgu_new(jz4760_cgu_clocks,
429bdbfc029SPaul Cercueil ARRAY_SIZE(jz4760_cgu_clocks), np);
430bdbfc029SPaul Cercueil if (!cgu) {
431bdbfc029SPaul Cercueil pr_err("%s: failed to initialise CGU\n", __func__);
432bdbfc029SPaul Cercueil return;
433bdbfc029SPaul Cercueil }
434bdbfc029SPaul Cercueil
435bdbfc029SPaul Cercueil retval = ingenic_cgu_register_clocks(cgu);
436bdbfc029SPaul Cercueil if (retval)
437bdbfc029SPaul Cercueil pr_err("%s: failed to register CGU Clocks\n", __func__);
438bdbfc029SPaul Cercueil
439bdbfc029SPaul Cercueil ingenic_cgu_register_syscore_ops(cgu);
440bdbfc029SPaul Cercueil }
441bdbfc029SPaul Cercueil
442bdbfc029SPaul Cercueil /* We only probe via devicetree, no need for a platform driver */
443bdbfc029SPaul Cercueil CLK_OF_DECLARE_DRIVER(jz4760_cgu, "ingenic,jz4760-cgu", jz4760_cgu_init);
444bdbfc029SPaul Cercueil
445bdbfc029SPaul Cercueil /* JZ4760B has some small differences, but we don't implement them. */
446bdbfc029SPaul Cercueil CLK_OF_DECLARE_DRIVER(jz4760b_cgu, "ingenic,jz4760b-cgu", jz4760_cgu_init);
447