Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/clk/allwinner/ccu_a64.c
39537 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2017,2018 Emmanuel Vadot <[email protected]>
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/systm.h>
30
#include <sys/bus.h>
31
#include <sys/rman.h>
32
#include <sys/kernel.h>
33
#include <sys/module.h>
34
#include <machine/bus.h>
35
36
#include <dev/fdt/simplebus.h>
37
38
#include <dev/ofw/ofw_bus.h>
39
#include <dev/ofw/ofw_bus_subr.h>
40
41
#include <dev/clk/clk_div.h>
42
#include <dev/clk/clk_fixed.h>
43
#include <dev/clk/clk_mux.h>
44
45
#include <dev/clk/allwinner/aw_ccung.h>
46
47
#include <dt-bindings/clock/sun50i-a64-ccu.h>
48
#include <dt-bindings/reset/sun50i-a64-ccu.h>
49
50
/* Non-exported clocks */
51
52
#define CLK_OSC_12M 0
53
#define CLK_PLL_CPUX 1
54
#define CLK_PLL_AUDIO_BASE 2
55
#define CLK_PLL_AUDIO 3
56
#define CLK_PLL_AUDIO_2X 4
57
#define CLK_PLL_AUDIO_4X 5
58
#define CLK_PLL_AUDIO_8X 6
59
#define CLK_PLL_VIDEO0 7
60
#define CLK_PLL_VIDEO0_2X 8
61
#define CLK_PLL_VE 9
62
#define CLK_PLL_DDR0 10
63
#define CLK_PLL_PERIPH0_2X 12
64
#define CLK_PLL_PERIPH1 13
65
#define CLK_PLL_PERIPH1_2X 14
66
#define CLK_PLL_VIDEO1 15
67
#define CLK_PLL_GPU 16
68
#define CLK_PLL_MIPI 17
69
#define CLK_PLL_HSIC 18
70
#define CLK_PLL_DE 19
71
#define CLK_PLL_DDR1 20
72
#define CLK_CPUX 21
73
#define CLK_AXI 22
74
#define CLK_APB 23
75
#define CLK_AHB1 24
76
#define CLK_APB1 25
77
#define CLK_APB2 26
78
#define CLK_AHB2 27
79
#define CLK_DRAM 94
80
81
#define CLK_MBUS 112
82
83
static struct aw_ccung_reset a64_ccu_resets[] = {
84
CCU_RESET(RST_USB_PHY0, 0x0cc, 0)
85
CCU_RESET(RST_USB_PHY1, 0x0cc, 1)
86
CCU_RESET(RST_USB_HSIC, 0x0cc, 2)
87
88
CCU_RESET(RST_BUS_MIPI_DSI, 0x2c0, 1)
89
CCU_RESET(RST_BUS_CE, 0x2c0, 5)
90
CCU_RESET(RST_BUS_DMA, 0x2c0, 6)
91
CCU_RESET(RST_BUS_MMC0, 0x2c0, 8)
92
CCU_RESET(RST_BUS_MMC1, 0x2c0, 9)
93
CCU_RESET(RST_BUS_MMC2, 0x2c0, 10)
94
CCU_RESET(RST_BUS_NAND, 0x2c0, 13)
95
CCU_RESET(RST_BUS_DRAM, 0x2c0, 14)
96
CCU_RESET(RST_BUS_EMAC, 0x2c0, 17)
97
CCU_RESET(RST_BUS_TS, 0x2c0, 18)
98
CCU_RESET(RST_BUS_HSTIMER, 0x2c0, 19)
99
CCU_RESET(RST_BUS_SPI0, 0x2c0, 20)
100
CCU_RESET(RST_BUS_SPI1, 0x2c0, 21)
101
CCU_RESET(RST_BUS_OTG, 0x2c0, 23)
102
CCU_RESET(RST_BUS_EHCI0, 0x2c0, 24)
103
CCU_RESET(RST_BUS_EHCI1, 0x2c0, 25)
104
CCU_RESET(RST_BUS_OHCI0, 0x2c0, 28)
105
CCU_RESET(RST_BUS_OHCI1, 0x2c0, 29)
106
107
CCU_RESET(RST_BUS_VE, 0x2c4, 0)
108
CCU_RESET(RST_BUS_TCON0, 0x2c4, 3)
109
CCU_RESET(RST_BUS_TCON1, 0x2c4, 4)
110
CCU_RESET(RST_BUS_DEINTERLACE, 0x2c4, 5)
111
CCU_RESET(RST_BUS_CSI, 0x2c4, 8)
112
CCU_RESET(RST_BUS_HDMI0, 0x2c4, 10)
113
CCU_RESET(RST_BUS_HDMI1, 0x2c4, 11)
114
CCU_RESET(RST_BUS_DE, 0x2c4, 12)
115
CCU_RESET(RST_BUS_GPU, 0x2c4, 20)
116
CCU_RESET(RST_BUS_MSGBOX, 0x2c4, 21)
117
CCU_RESET(RST_BUS_SPINLOCK, 0x2c4, 22)
118
CCU_RESET(RST_BUS_DBG, 0x2c4, 31)
119
120
CCU_RESET(RST_BUS_LVDS, 0x2C8, 31)
121
122
CCU_RESET(RST_BUS_CODEC, 0x2D0, 0)
123
CCU_RESET(RST_BUS_SPDIF, 0x2D0, 1)
124
CCU_RESET(RST_BUS_THS, 0x2D0, 8)
125
CCU_RESET(RST_BUS_I2S0, 0x2D0, 12)
126
CCU_RESET(RST_BUS_I2S1, 0x2D0, 13)
127
CCU_RESET(RST_BUS_I2S2, 0x2D0, 14)
128
129
CCU_RESET(RST_BUS_I2C0, 0x2D8, 0)
130
CCU_RESET(RST_BUS_I2C1, 0x2D8, 1)
131
CCU_RESET(RST_BUS_I2C2, 0x2D8, 2)
132
CCU_RESET(RST_BUS_SCR, 0x2D8, 5)
133
CCU_RESET(RST_BUS_UART0, 0x2D8, 16)
134
CCU_RESET(RST_BUS_UART1, 0x2D8, 17)
135
CCU_RESET(RST_BUS_UART2, 0x2D8, 18)
136
CCU_RESET(RST_BUS_UART3, 0x2D8, 19)
137
CCU_RESET(RST_BUS_UART4, 0x2D8, 20)
138
};
139
140
static struct aw_ccung_gate a64_ccu_gates[] = {
141
CCU_GATE(CLK_BUS_MIPI_DSI, "bus-mipi-dsi", "ahb1", 0x60, 1)
142
CCU_GATE(CLK_BUS_CE, "bus-ce", "ahb1", 0x60, 5)
143
CCU_GATE(CLK_BUS_DMA, "bus-dma", "ahb1", 0x60, 6)
144
CCU_GATE(CLK_BUS_MMC0, "bus-mmc0", "ahb1", 0x60, 8)
145
CCU_GATE(CLK_BUS_MMC1, "bus-mmc1", "ahb1", 0x60, 9)
146
CCU_GATE(CLK_BUS_MMC2, "bus-mmc2", "ahb1", 0x60, 10)
147
CCU_GATE(CLK_BUS_NAND, "bus-nand", "ahb1", 0x60, 13)
148
CCU_GATE(CLK_BUS_DRAM, "bus-dram", "ahb1", 0x60, 14)
149
CCU_GATE(CLK_BUS_EMAC, "bus-emac", "ahb2", 0x60, 16)
150
CCU_GATE(CLK_BUS_TS, "bus-ts", "ahb1", 0x60, 18)
151
CCU_GATE(CLK_BUS_HSTIMER, "bus-hstimer", "ahb1", 0x60, 19)
152
CCU_GATE(CLK_BUS_SPI0, "bus-spi0", "ahb1", 0x60, 20)
153
CCU_GATE(CLK_BUS_SPI1, "bus-spi1", "ahb1", 0x60, 21)
154
CCU_GATE(CLK_BUS_OTG, "bus-otg", "ahb1", 0x60, 23)
155
CCU_GATE(CLK_BUS_EHCI0, "bus-ehci0", "ahb1", 0x60, 24)
156
CCU_GATE(CLK_BUS_EHCI1, "bus-ehci1", "ahb2", 0x60, 25)
157
CCU_GATE(CLK_BUS_OHCI0, "bus-ohci0", "ahb1", 0x60, 28)
158
CCU_GATE(CLK_BUS_OHCI1, "bus-ohci1", "ahb2", 0x60, 29)
159
160
CCU_GATE(CLK_BUS_VE, "bus-ve", "ahb1", 0x64, 0)
161
CCU_GATE(CLK_BUS_TCON0, "bus-tcon0", "ahb1", 0x64, 3)
162
CCU_GATE(CLK_BUS_TCON1, "bus-tcon1", "ahb1", 0x64, 4)
163
CCU_GATE(CLK_BUS_DEINTERLACE, "bus-deinterlace", "ahb1", 0x64, 5)
164
CCU_GATE(CLK_BUS_CSI, "bus-csi", "ahb1", 0x64, 8)
165
CCU_GATE(CLK_BUS_HDMI, "bus-hdmi", "ahb1", 0x64, 11)
166
CCU_GATE(CLK_BUS_DE, "bus-de", "ahb1", 0x64, 12)
167
CCU_GATE(CLK_BUS_GPU, "bus-gpu", "ahb1", 0x64, 20)
168
CCU_GATE(CLK_BUS_MSGBOX, "bus-msgbox", "ahb1", 0x64, 21)
169
CCU_GATE(CLK_BUS_SPINLOCK, "bus-spinlock", "ahb1", 0x64, 22)
170
171
CCU_GATE(CLK_BUS_CODEC, "bus-codec", "apb1", 0x68, 0)
172
CCU_GATE(CLK_BUS_SPDIF, "bus-spdif", "apb1", 0x68, 1)
173
CCU_GATE(CLK_BUS_PIO, "bus-pio", "apb1", 0x68, 5)
174
CCU_GATE(CLK_BUS_THS, "bus-ths", "apb1", 0x68, 8)
175
CCU_GATE(CLK_BUS_I2S0, "bus-i2s0", "apb1", 0x68, 12)
176
CCU_GATE(CLK_BUS_I2S1, "bus-i2s1", "apb1", 0x68, 13)
177
CCU_GATE(CLK_BUS_I2S2, "bus-i2s2", "apb1", 0x68, 14)
178
179
CCU_GATE(CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x6C, 0)
180
CCU_GATE(CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x6C, 1)
181
CCU_GATE(CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x6C, 2)
182
CCU_GATE(CLK_BUS_SCR, "bus-src", "apb2", 0x6C, 5)
183
CCU_GATE(CLK_BUS_UART0, "bus-uart0", "apb2", 0x6C, 16)
184
CCU_GATE(CLK_BUS_UART1, "bus-uart1", "apb2", 0x6C, 17)
185
CCU_GATE(CLK_BUS_UART2, "bus-uart2", "apb2", 0x6C, 18)
186
CCU_GATE(CLK_BUS_UART3, "bus-uart3", "apb2", 0x6C, 19)
187
CCU_GATE(CLK_BUS_UART4, "bus-uart4", "apb2", 0x6C, 20)
188
189
CCU_GATE(CLK_BUS_DBG, "bus-dbg", "ahb1", 0x70, 7)
190
191
CCU_GATE(CLK_THS, "ths", "thsdiv", 0x74, 31)
192
193
CCU_GATE(CLK_USB_PHY0, "usb-phy0", "osc24M", 0xcc, 8)
194
CCU_GATE(CLK_USB_PHY1, "usb-phy1", "osc24M", 0xcc, 9)
195
CCU_GATE(CLK_USB_HSIC, "usb-hsic", "pll_hsic", 0xcc, 10)
196
CCU_GATE(CLK_USB_HSIC_12M, "usb-hsic-12M", "osc12M", 0xcc, 11)
197
CCU_GATE(CLK_USB_OHCI0, "usb-ohci0", "osc12M", 0xcc, 16)
198
CCU_GATE(CLK_USB_OHCI1, "usb-ohci1", "usb-ohci0", 0xcc, 17)
199
200
CCU_GATE(CLK_DRAM_VE, "dram-ve", "dram", 0x100, 0)
201
CCU_GATE(CLK_DRAM_CSI, "dram-csi", "dram", 0x100, 1)
202
CCU_GATE(CLK_DRAM_DEINTERLACE, "dram-deinterlace", "dram", 0x100, 2)
203
CCU_GATE(CLK_DRAM_TS, "dram-ts", "dram", 0x100, 3)
204
205
CCU_GATE(CLK_CSI_MISC, "csi-misc", "osc24M", 0x130, 31)
206
207
CCU_GATE(CLK_AC_DIG_4X, "ac-dig-4x", "pll_audio-4x", 0x140, 30)
208
CCU_GATE(CLK_AC_DIG, "ac-dig", "pll_audio", 0x140, 31)
209
210
CCU_GATE(CLK_AVS, "avs", "osc24M", 0x144, 31)
211
212
CCU_GATE(CLK_HDMI_DDC, "hdmi-ddc", "osc24M", 0x154, 31)
213
};
214
215
static const char *osc12m_parents[] = {"osc24M"};
216
FIXED_CLK(osc12m_clk,
217
CLK_OSC_12M, /* id */
218
"osc12M", /* name */
219
osc12m_parents, /* parent */
220
0, /* freq */
221
1, /* mult */
222
2, /* div */
223
0); /* flags */
224
225
static const char *pll_cpux_parents[] = {"osc24M"};
226
NKMP_CLK(pll_cpux_clk,
227
CLK_PLL_CPUX, /* id */
228
"pll_cpux", pll_cpux_parents, /* name, parents */
229
0x00, /* offset */
230
8, 5, 0, 0, /* n factor */
231
4, 2, 0, 0, /* k factor */
232
0, 2, 0, 0, /* m factor */
233
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* p factor */
234
31, /* gate */
235
28, 1000, /* lock */
236
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK | AW_CLK_SCALE_CHANGE); /* flags */
237
238
static const char *pll_audio_parents[] = {"osc24M"};
239
NKMP_CLK(pll_audio_clk,
240
CLK_PLL_AUDIO, /* id */
241
"pll_audio", pll_audio_parents, /* name, parents */
242
0x08, /* offset */
243
8, 7, 0, 0, /* n factor */
244
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
245
0, 5, 0, 0, /* m factor */
246
16, 4, 0, 0, /* p factor */
247
31, /* gate */
248
28, 1000, /* lock */
249
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
250
251
static const char *pll_audio_mult_parents[] = {"pll_audio"};
252
FIXED_CLK(pll_audio_2x_clk,
253
CLK_PLL_AUDIO_2X, /* id */
254
"pll_audio-2x", /* name */
255
pll_audio_mult_parents, /* parent */
256
0, /* freq */
257
2, /* mult */
258
1, /* div */
259
0); /* flags */
260
FIXED_CLK(pll_audio_4x_clk,
261
CLK_PLL_AUDIO_4X, /* id */
262
"pll_audio-4x", /* name */
263
pll_audio_mult_parents, /* parent */
264
0, /* freq */
265
4, /* mult */
266
1, /* div */
267
0); /* flags */
268
FIXED_CLK(pll_audio_8x_clk,
269
CLK_PLL_AUDIO_8X, /* id */
270
"pll_audio-8x", /* name */
271
pll_audio_mult_parents, /* parent */
272
0, /* freq */
273
8, /* mult */
274
1, /* div */
275
0); /* flags */
276
277
static const char *pll_video0_parents[] = {"osc24M"};
278
FRAC_CLK(pll_video0_clk,
279
CLK_PLL_VIDEO0, /* id */
280
"pll_video0", pll_video0_parents, /* name, parents */
281
0x10, /* offset */
282
8, 7, 0, 0, /* n factor */
283
0, 4, 0, 0, /* m factor */
284
31, 28, 1000, /* gate, lock, lock retries */
285
AW_CLK_HAS_LOCK, /* flags */
286
270000000, 297000000, /* freq0, freq1 */
287
24, 25, /* mode sel, freq sel */
288
192000000, 600000000); /* min freq, max freq */
289
static const char *pll_video0_2x_parents[] = {"pll_video0"};
290
FIXED_CLK(pll_video0_2x_clk,
291
CLK_PLL_VIDEO0_2X, /* id */
292
"pll_video0-2x", /* name */
293
pll_video0_2x_parents, /* parent */
294
0, /* freq */
295
2, /* mult */
296
1, /* div */
297
0); /* flags */
298
299
static const char *pll_ve_parents[] = {"osc24M"};
300
FRAC_CLK(pll_ve_clk,
301
CLK_PLL_VE, /* id */
302
"pll_ve", pll_ve_parents, /* name, parents */
303
0x18, /* offset */
304
8, 7, 0, 0, /* n factor */
305
0, 4, 0, 0, /* m factor */
306
31, 28, 1000, /* gate, lock, lock retries */
307
AW_CLK_HAS_LOCK, /* flags */
308
270000000, 297000000, /* freq0, freq1 */
309
24, 25, /* mode sel, freq sel */
310
192000000, 600000000); /* min freq, max freq */
311
312
static const char *pll_ddr0_parents[] = {"osc24M"};
313
NKMP_CLK_WITH_UPDATE(pll_ddr0_clk,
314
CLK_PLL_DDR0, /* id */
315
"pll_ddr0", pll_ddr0_parents, /* name, parents */
316
0x20, /* offset */
317
8, 5, 0, 0, /* n factor */
318
4, 2, 0, 0, /* k factor */
319
0, 2, 0, 0, /* m factor */
320
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
321
31, /* gate */
322
28, 1000, /* lock */
323
20, /* update */
324
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
325
326
static const char *pll_periph0_2x_parents[] = {"osc24M"};
327
static const char *pll_periph0_parents[] = {"pll_periph0_2x"};
328
NKMP_CLK(pll_periph0_2x_clk,
329
CLK_PLL_PERIPH0_2X, /* id */
330
"pll_periph0_2x", pll_periph0_2x_parents, /* name, parents */
331
0x28, /* offset */
332
8, 5, 0, 0, /* n factor */
333
4, 2, 0, 0, /* k factor */
334
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
335
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
336
31, /* gate */
337
28, 1000, /* lock */
338
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
339
FIXED_CLK(pll_periph0_clk,
340
CLK_PLL_PERIPH0, /* id */
341
"pll_periph0", /* name */
342
pll_periph0_parents, /* parent */
343
0, /* freq */
344
1, /* mult */
345
2, /* div */
346
0); /* flags */
347
348
static const char *pll_periph1_2x_parents[] = {"osc24M"};
349
static const char *pll_periph1_parents[] = {"pll_periph1_2x"};
350
NKMP_CLK(pll_periph1_2x_clk,
351
CLK_PLL_PERIPH1_2X, /* id */
352
"pll_periph1_2x", pll_periph1_2x_parents, /* name, parents */
353
0x2C, /* offset */
354
8, 5, 0, 0, /* n factor */
355
4, 2, 0, 0, /* k factor */
356
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
357
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
358
31, /* gate */
359
28, 1000, /* lock */
360
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
361
FIXED_CLK(pll_periph1_clk,
362
CLK_PLL_PERIPH1, /* id */
363
"pll_periph1", /* name */
364
pll_periph1_parents, /* parent */
365
0, /* freq */
366
1, /* mult */
367
2, /* div */
368
0); /* flags */
369
370
static const char *pll_video1_parents[] = {"osc24M"};
371
FRAC_CLK(pll_video1_clk,
372
CLK_PLL_VIDEO1, /* id */
373
"pll_video1", pll_video1_parents, /* name, parents */
374
0x30, /* offset */
375
8, 7, 0, 0, /* n factor */
376
0, 4, 0, 0, /* m factor */
377
31, 28, 1000, /* gate, lock, lock retries */
378
AW_CLK_HAS_LOCK, /* flags */
379
270000000, 297000000, /* freq0, freq1 */
380
24, 25, /* mode sel, freq sel */
381
192000000, 600000000); /* min freq, max freq */
382
383
static const char *pll_gpu_parents[] = {"osc24M"};
384
FRAC_CLK(pll_gpu_clk,
385
CLK_PLL_GPU, /* id */
386
"pll_gpu", pll_gpu_parents, /* name, parents */
387
0x38, /* offset */
388
8, 7, 0, 0, /* n factor */
389
0, 4, 0, 0, /* m factor */
390
31, 28, 1000, /* gate, lock, lock retries */
391
AW_CLK_HAS_LOCK, /* flags */
392
270000000, 297000000, /* freq0, freq1 */
393
24, 25, /* mode sel, freq sel */
394
192000000, 600000000); /* min freq, max freq */
395
396
static const char *pll_mipi_parents[] = {"pll_video0"};
397
MIPI_CLK(pll_mipi_clk,
398
CLK_PLL_MIPI,
399
"pll_mipi", pll_mipi_parents,
400
0x40,
401
4, 2, AW_CLK_FACTOR_MIN_VALUE, 2,
402
0, 3,
403
8, 4,
404
31, 28);
405
406
static const char *pll_hsic_parents[] = {"osc24M"};
407
FRAC_CLK(pll_hsic_clk,
408
CLK_PLL_HSIC, /* id */
409
"pll_hsic", pll_hsic_parents, /* name, parents */
410
0x44, /* offset */
411
8, 7, 0, 0, /* n factor */
412
0, 4, 0, 0, /* m factor */
413
31, 28, 1000, /* gate, lock, lock retries */
414
AW_CLK_HAS_LOCK, /* flags */
415
270000000, 297000000, /* freq0, freq1 */
416
24, 25, /* mode sel, freq sel */
417
192000000, 600000000); /* min freq, max freq */
418
419
static const char *pll_de_parents[] = {"osc24M"};
420
FRAC_CLK(pll_de_clk,
421
CLK_PLL_DE, /* id */
422
"pll_de", pll_de_parents, /* name, parents */
423
0x48, /* offset */
424
8, 7, 0, 0, /* n factor */
425
0, 4, 0, 0, /* m factor */
426
31, 28, 1000, /* gate, lock, lock retries */
427
AW_CLK_HAS_LOCK, /* flags */
428
270000000, 297000000, /* freq0, freq1 */
429
24, 25, /* mode sel, freq sel */
430
192000000, 600000000); /* min freq, max freq */
431
432
static const char *pll_ddr1_parents[] = {"osc24M"};
433
NKMP_CLK_WITH_UPDATE(pll_ddr1_clk,
434
CLK_PLL_DDR1, /* id */
435
"pll_ddr1", pll_ddr1_parents, /* name, parents */
436
0x4C, /* offset */
437
8, 7, 0, 0, /* n factor */
438
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
439
0, 2, 0, 0, /* m factor */
440
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
441
31, /* gate */
442
28, 1000, /* lock */
443
20, /* update */
444
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
445
446
static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux"};
447
MUX_CLK(cpux_clk,
448
CLK_CPUX, /* id */
449
"cpux", cpux_parents, /* name, parents */
450
0x50, 16, 2); /* offset, shift, width */
451
452
static const char *axi_parents[] = {"cpux"};
453
DIV_CLK(axi_clk,
454
CLK_AXI, /* id */
455
"axi", axi_parents, /* name, parents */
456
0x50, /* offset */
457
0, 2, /* shift, width */
458
0, NULL); /* flags, div table */
459
460
static const char *apb_parents[] = {"cpux"};
461
DIV_CLK(apb_clk,
462
CLK_APB, /* id */
463
"apb", apb_parents, /* name, parents */
464
0x50, /* offset */
465
8, 2, /* shift, width */
466
0, NULL); /* flags, div table */
467
468
static const char *ahb1_parents[] = {"osc32k", "osc24M", "axi", "pll_periph0"};
469
PREDIV_CLK(ahb1_clk, CLK_AHB1, /* id */
470
"ahb1", ahb1_parents, /* name, parents */
471
0x54, /* offset */
472
12, 2, /* mux */
473
4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
474
6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
475
12, 2, 3); /* prediv condition */
476
477
static const char *apb1_parents[] = {"ahb1"};
478
static struct clk_div_table apb1_div_table[] = {
479
{ .value = 0, .divider = 2, },
480
{ .value = 1, .divider = 2, },
481
{ .value = 2, .divider = 4, },
482
{ .value = 3, .divider = 8, },
483
{ },
484
};
485
DIV_CLK(apb1_clk,
486
CLK_APB1, /* id */
487
"apb1", apb1_parents, /* name, parents */
488
0x54, /* offset */
489
8, 2, /* shift, width */
490
CLK_DIV_WITH_TABLE, /* flags */
491
apb1_div_table); /* div table */
492
493
static const char *apb2_parents[] = {"osc32k", "osc24M", "pll_periph0_2x", "pll_periph0_2x"};
494
NM_CLK(apb2_clk,
495
CLK_APB2, /* id */
496
"apb2", apb2_parents, /* name, parents */
497
0x58, /* offset */
498
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
499
0, 5, 0, 0, /* m factor */
500
24, 2, /* mux */
501
0, /* gate */
502
AW_CLK_HAS_MUX);
503
504
static const char *ahb2_parents[] = {"ahb1", "pll_periph0"};
505
PREDIV_CLK(ahb2_clk, CLK_AHB2, /* id */
506
"ahb2", ahb2_parents, /* name, parents */
507
0x5c, /* offset */
508
0, 2, /* mux */
509
0, 0, 1, AW_CLK_FACTOR_FIXED, /* div */
510
0, 0, 2, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
511
0, 2, 1); /* prediv condition */
512
513
static const char *ths_parents[] = {"osc24M"};
514
static struct clk_div_table ths_div_table[] = {
515
{ .value = 0, .divider = 1, },
516
{ .value = 1, .divider = 2, },
517
{ .value = 2, .divider = 4, },
518
{ .value = 3, .divider = 6, },
519
{ },
520
};
521
DIV_CLK(ths_clk,
522
0, /* id */
523
"thsdiv", ths_parents, /* name, parents */
524
0x74, /* offset */
525
0, 2, /* div shift, div width */
526
CLK_DIV_WITH_TABLE, /* flags */
527
ths_div_table); /* div table */
528
529
static const char *mod_parents[] = {"osc24M", "pll_periph0_2x", "pll_periph1_2x"};
530
NM_CLK(nand_clk,
531
CLK_NAND, "nand", mod_parents, /* id, name, parents */
532
0x80, /* offset */
533
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
534
0, 4, 0, 0, /* m factor */
535
24, 2, /* mux */
536
31, /* gate */
537
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
538
539
NM_CLK(mmc0_clk,
540
CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
541
0x88, /* offset */
542
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
543
0, 4, 0, 0, /* m factor */
544
24, 2, /* mux */
545
31, /* gate */
546
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
547
AW_CLK_REPARENT); /* flags */
548
549
NM_CLK(mmc1_clk,
550
CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
551
0x8c, /* offset */
552
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
553
0, 4, 0, 0, /* m factor */
554
24, 2, /* mux */
555
31, /* gate */
556
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
557
AW_CLK_REPARENT); /* flags */
558
559
NM_CLK(mmc2_clk,
560
CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
561
0x90, /* offset */
562
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
563
0, 4, 0, 0, /* m factor */
564
24, 2, /* mux */
565
31, /* gate */
566
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
567
AW_CLK_REPARENT); /* flags */
568
569
static const char *ts_parents[] = {"osc24M", "pll_periph0"};
570
NM_CLK(ts_clk,
571
CLK_TS, "ts", ts_parents, /* id, name, parents */
572
0x98, /* offset */
573
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
574
0, 4, 0, 0, /* m factor */
575
24, 2, /* mux */
576
31, /* gate */
577
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
578
579
NM_CLK(ce_clk,
580
CLK_CE, "ce", mod_parents, /* id, name, parents */
581
0x9C, /* offset */
582
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
583
0, 4, 0, 0, /* m factor */
584
24, 2, /* mux */
585
31, /* gate */
586
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
587
588
NM_CLK(spi0_clk,
589
CLK_SPI0, "spi0", mod_parents, /* id, name, parents */
590
0xA0, /* offset */
591
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
592
0, 4, 0, 0, /* m factor */
593
24, 2, /* mux */
594
31, /* gate */
595
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
596
AW_CLK_REPARENT); /* flags */
597
598
NM_CLK(spi1_clk,
599
CLK_SPI1, "spi1", mod_parents, /* id, name, parents */
600
0xA4, /* offset */
601
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
602
0, 4, 0, 0, /* m factor */
603
24, 2, /* mux */
604
31, /* gate */
605
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
606
AW_CLK_REPARENT); /* flags */
607
608
static const char *i2s_parents[] = {"pll_audio-8x", "pll_audio-4x", "pll_audio-2x", "pll_audio"};
609
MUX_CLK(i2s0mux_clk,
610
0, "i2s0mux", i2s_parents, /* id, name, parents */
611
0xb0, 16, 2); /* offset, mux shift, mux width */
612
MUX_CLK(i2s1mux_clk,
613
0, "i2s1mux", i2s_parents, /* id, name, parents */
614
0xb4, 16, 2); /* offset, mux shift, mux width */
615
MUX_CLK(i2s2mux_clk,
616
0, "i2s2mux", i2s_parents, /* id, name, parents */
617
0xb8, 16, 2); /* offset, mux shift, mux width */
618
619
static const char *spdif_parents[] = {"pll_audio"};
620
M_CLK(spdif_clk,
621
CLK_SPDIF, "spdif", spdif_parents, /* id, name, parents */
622
0xC0, /* offset */
623
0, 4, 0, 0, /* m factor */
624
0, 0, /* mux */
625
31, /* gate */
626
AW_CLK_HAS_GATE); /* flags */
627
628
/* USBPHY clk sel */
629
630
/* DRAM needs update bit */
631
static const char *dram_parents[] = {"pll_ddr0", "pll_ddr1"};
632
M_CLK(dram_clk,
633
CLK_DRAM, "dram", dram_parents, /* id, name, parents */
634
0xF4, /* offset */
635
0, 2, 0, 0, /* m factor */
636
20, 2, /* mux */
637
0, /* gate */
638
AW_CLK_HAS_MUX); /* flags */
639
640
static const char *de_parents[] = {"pll_periph0_2x", "pll_de"};
641
M_CLK(de_clk,
642
CLK_DE, "de", de_parents, /* id, name, parents */
643
0x104, /* offset */
644
0, 4, 0, 0, /* m factor */
645
24, 2, /* mux */
646
31, /* gate */
647
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
648
649
static const char *tcon0_parents[] = {"pll_mipi", NULL, "pll_video0-2x"};
650
MUX_CLK(tcon0_clk,
651
CLK_TCON0, /* id */
652
"tcon0", tcon0_parents, /* name, parents */
653
0x118, 24, 2); /* offset, shift, width */
654
655
static const char *tcon1_parents[] = {"pll_video0", NULL, "pll_video1"};
656
M_CLK(tcon1_clk,
657
CLK_TCON1, "tcon1", tcon1_parents, /* id, name, parents */
658
0x11C, /* offset */
659
0, 5, 0, 0, /* m factor */
660
24, 2, /* mux */
661
31, /* gate */
662
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE |
663
AW_CLK_SET_PARENT); /* flags */
664
665
static const char *deinterlace_parents[] = {"pll_periph0", "pll_periph1"};
666
M_CLK(deinterlace_clk,
667
CLK_DEINTERLACE, "deinterlace", deinterlace_parents, /* id, name, parents */
668
0x124, /* offset */
669
0, 4, 0, 0, /* m factor */
670
24, 2, /* mux */
671
31, /* gate */
672
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
673
674
static const char *csi_sclk_parents[] = {"pll_periph0", "pll_periph1"};
675
M_CLK(csi_sclk_clk,
676
CLK_CSI_SCLK, "csi-sclk", csi_sclk_parents, /* id, name, parents */
677
0x134, /* offset */
678
16, 4, 0, 0, /* m factor */
679
24, 2, /* mux */
680
31, /* gate */
681
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
682
683
static const char *csi_mclk_parents[] = {"osc24M", "pll_video0", "pll_periph1"};
684
M_CLK(csi_mclk_clk,
685
CLK_CSI_MCLK, "csi-mclk", csi_mclk_parents, /* id, name, parents */
686
0x134, /* offset */
687
0, 4, 0, 0, /* m factor */
688
8, 2, /* mux */
689
15, /* gate */
690
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
691
692
static const char *ve_parents[] = {"pll_ve"};
693
M_CLK(ve_clk,
694
CLK_VE, "ve", ve_parents, /* id, name, parents */
695
0x13C, /* offset */
696
16, 3, 0, 0, /* m factor */
697
0, 0, /* mux */
698
31, /* gate */
699
AW_CLK_HAS_GATE); /* flags */
700
701
static const char *hdmi_parents[] = {"pll_video0"};
702
M_CLK(hdmi_clk,
703
CLK_HDMI, "hdmi", hdmi_parents, /* id, name, parents */
704
0x150, /* offset */
705
0, 4, 0, 0, /* m factor */
706
24, 2, /* mux */
707
31, /* gate */
708
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE | AW_CLK_SET_PARENT); /* flags */
709
710
static const char *mbus_parents[] = {"osc24M", "pll_periph0_2x", "pll_ddr0"};
711
M_CLK(mbus_clk,
712
CLK_MBUS, "mbus", mbus_parents, /* id, name, parents */
713
0x15C, /* offset */
714
0, 3, 0, 0, /* m factor */
715
24, 2, /* mux */
716
31, /* gate */
717
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
718
719
static const char *gpu_parents[] = {"pll_gpu"};
720
M_CLK(gpu_clk,
721
CLK_GPU, "gpu", gpu_parents, /* id, name, parents */
722
0x1A0, /* offset */
723
0, 2, 0, 0, /* m factor */
724
0, 0, /* mux */
725
31, /* gate */
726
AW_CLK_HAS_GATE); /* flags */
727
728
static struct aw_ccung_clk a64_ccu_clks[] = {
729
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_cpux_clk},
730
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_audio_clk},
731
{ .type = AW_CLK_FRAC, .clk.frac = &pll_video0_clk},
732
{ .type = AW_CLK_FRAC, .clk.frac = &pll_ve_clk},
733
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr0_clk},
734
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph0_2x_clk},
735
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_periph1_2x_clk},
736
{ .type = AW_CLK_FRAC, .clk.frac = &pll_video1_clk},
737
{ .type = AW_CLK_FRAC, .clk.frac = &pll_gpu_clk},
738
{ .type = AW_CLK_MIPI, .clk.mipi = &pll_mipi_clk},
739
{ .type = AW_CLK_FRAC, .clk.frac = &pll_hsic_clk},
740
{ .type = AW_CLK_FRAC, .clk.frac = &pll_de_clk},
741
{ .type = AW_CLK_NKMP, .clk.nkmp = &pll_ddr1_clk},
742
743
{ .type = AW_CLK_NM, .clk.nm = &apb2_clk},
744
{ .type = AW_CLK_NM, .clk.nm = &nand_clk},
745
{ .type = AW_CLK_NM, .clk.nm = &mmc0_clk},
746
{ .type = AW_CLK_NM, .clk.nm = &mmc1_clk},
747
{ .type = AW_CLK_NM, .clk.nm = &mmc2_clk},
748
{ .type = AW_CLK_NM, .clk.nm = &ts_clk},
749
{ .type = AW_CLK_NM, .clk.nm = &ce_clk},
750
{ .type = AW_CLK_NM, .clk.nm = &spi0_clk},
751
{ .type = AW_CLK_NM, .clk.nm = &spi1_clk},
752
{ .type = AW_CLK_M, .clk.m = &spdif_clk},
753
{ .type = AW_CLK_M, .clk.m = &dram_clk},
754
{ .type = AW_CLK_M, .clk.m = &de_clk},
755
{ .type = AW_CLK_M, .clk.m = &tcon1_clk},
756
{ .type = AW_CLK_M, .clk.m = &deinterlace_clk},
757
{ .type = AW_CLK_M, .clk.m = &csi_sclk_clk},
758
{ .type = AW_CLK_M, .clk.m = &csi_mclk_clk},
759
{ .type = AW_CLK_M, .clk.m = &ve_clk},
760
{ .type = AW_CLK_M, .clk.m = &hdmi_clk},
761
{ .type = AW_CLK_M, .clk.m = &mbus_clk},
762
{ .type = AW_CLK_M, .clk.m = &gpu_clk},
763
{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb1_clk},
764
{ .type = AW_CLK_PREDIV_MUX, .clk.prediv_mux = &ahb2_clk},
765
{ .type = AW_CLK_MUX, .clk.mux = &cpux_clk},
766
{ .type = AW_CLK_MUX, .clk.mux = &i2s0mux_clk},
767
{ .type = AW_CLK_MUX, .clk.mux = &i2s1mux_clk},
768
{ .type = AW_CLK_MUX, .clk.mux = &i2s2mux_clk},
769
{ .type = AW_CLK_MUX, .clk.mux = &tcon0_clk},
770
{ .type = AW_CLK_DIV, .clk.div = &axi_clk},
771
{ .type = AW_CLK_DIV, .clk.div = &apb1_clk},
772
{ .type = AW_CLK_DIV, .clk.div = &apb_clk},
773
{ .type = AW_CLK_DIV, .clk.div = &ths_clk},
774
{ .type = AW_CLK_FIXED, .clk.fixed = &osc12m_clk},
775
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_periph0_clk},
776
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_periph1_clk},
777
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_audio_2x_clk},
778
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_audio_4x_clk},
779
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_audio_8x_clk},
780
{ .type = AW_CLK_FIXED, .clk.fixed = &pll_video0_2x_clk},
781
};
782
783
static struct aw_clk_init a64_init_clks[] = {
784
{"ahb1", "pll_periph0", 0, false},
785
{"ahb2", "pll_periph0", 0, false},
786
{"dram", "pll_ddr0", 0, false},
787
{"pll_de", NULL, 432000000, true},
788
{"de", "pll_de", 0, true},
789
};
790
791
static int
792
ccu_a64_probe(device_t dev)
793
{
794
795
if (!ofw_bus_status_okay(dev))
796
return (ENXIO);
797
798
if (!ofw_bus_is_compatible(dev, "allwinner,sun50i-a64-ccu"))
799
return (ENXIO);
800
801
device_set_desc(dev, "Allwinner A64 Clock Control Unit NG");
802
return (BUS_PROBE_DEFAULT);
803
}
804
805
static int
806
ccu_a64_attach(device_t dev)
807
{
808
struct aw_ccung_softc *sc;
809
810
sc = device_get_softc(dev);
811
812
sc->resets = a64_ccu_resets;
813
sc->nresets = nitems(a64_ccu_resets);
814
sc->gates = a64_ccu_gates;
815
sc->ngates = nitems(a64_ccu_gates);
816
sc->clks = a64_ccu_clks;
817
sc->nclks = nitems(a64_ccu_clks);
818
sc->clk_init = a64_init_clks;
819
sc->n_clk_init = nitems(a64_init_clks);
820
821
return (aw_ccung_attach(dev));
822
}
823
824
static device_method_t ccu_a64ng_methods[] = {
825
/* Device interface */
826
DEVMETHOD(device_probe, ccu_a64_probe),
827
DEVMETHOD(device_attach, ccu_a64_attach),
828
829
DEVMETHOD_END
830
};
831
832
DEFINE_CLASS_1(ccu_a64ng, ccu_a64ng_driver, ccu_a64ng_methods,
833
sizeof(struct aw_ccung_softc), aw_ccung_driver);
834
835
EARLY_DRIVER_MODULE(ccu_a64ng, simplebus, ccu_a64ng_driver, 0, 0,
836
BUS_PASS_RESOURCE + BUS_PASS_ORDER_MIDDLE);
837
838