Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/clk/berlin/bg2.c
26282 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright (c) 2014 Marvell Technology Group Ltd.
4
*
5
* Sebastian Hesselbarth <[email protected]>
6
* Alexandre Belloni <[email protected]>
7
*/
8
9
#include <linux/clk.h>
10
#include <linux/clk-provider.h>
11
#include <linux/io.h>
12
#include <linux/kernel.h>
13
#include <linux/of.h>
14
#include <linux/of_address.h>
15
#include <linux/slab.h>
16
17
#include <dt-bindings/clock/berlin2.h>
18
19
#include "berlin2-avpll.h"
20
#include "berlin2-div.h"
21
#include "berlin2-pll.h"
22
#include "common.h"
23
24
#define REG_PINMUX0 0x0000
25
#define REG_PINMUX1 0x0004
26
#define REG_SYSPLLCTL0 0x0014
27
#define REG_SYSPLLCTL4 0x0024
28
#define REG_MEMPLLCTL0 0x0028
29
#define REG_MEMPLLCTL4 0x0038
30
#define REG_CPUPLLCTL0 0x003c
31
#define REG_CPUPLLCTL4 0x004c
32
#define REG_AVPLLCTL0 0x0050
33
#define REG_AVPLLCTL31 0x00cc
34
#define REG_AVPLLCTL62 0x0148
35
#define REG_PLLSTATUS 0x014c
36
#define REG_CLKENABLE 0x0150
37
#define REG_CLKSELECT0 0x0154
38
#define REG_CLKSELECT1 0x0158
39
#define REG_CLKSELECT2 0x015c
40
#define REG_CLKSELECT3 0x0160
41
#define REG_CLKSWITCH0 0x0164
42
#define REG_CLKSWITCH1 0x0168
43
#define REG_RESET_TRIGGER 0x0178
44
#define REG_RESET_STATUS0 0x017c
45
#define REG_RESET_STATUS1 0x0180
46
#define REG_SW_GENERIC0 0x0184
47
#define REG_SW_GENERIC3 0x0190
48
#define REG_PRODUCTID 0x01cc
49
#define REG_PRODUCTID_EXT 0x01d0
50
#define REG_GFX3DCORE_CLKCTL 0x022c
51
#define REG_GFX3DSYS_CLKCTL 0x0230
52
#define REG_ARC_CLKCTL 0x0234
53
#define REG_VIP_CLKCTL 0x0238
54
#define REG_SDIO0XIN_CLKCTL 0x023c
55
#define REG_SDIO1XIN_CLKCTL 0x0240
56
#define REG_GFX3DEXTRA_CLKCTL 0x0244
57
#define REG_GFX3D_RESET 0x0248
58
#define REG_GC360_CLKCTL 0x024c
59
#define REG_SDIO_DLLMST_CLKCTL 0x0250
60
61
/*
62
* BG2/BG2CD SoCs have the following audio/video I/O units:
63
*
64
* audiohd: HDMI TX audio
65
* audio0: 7.1ch TX
66
* audio1: 2ch TX
67
* audio2: 2ch RX
68
* audio3: SPDIF TX
69
* video0: HDMI video
70
* video1: Secondary video
71
* video2: SD auxiliary video
72
*
73
* There are no external audio clocks (ACLKI0, ACLKI1) and
74
* only one external video clock (VCLKI0).
75
*
76
* Currently missing bits and pieces:
77
* - audio_fast_pll is unknown
78
* - audiohd_pll is unknown
79
* - video0_pll is unknown
80
* - audio[023], audiohd parent pll is assumed to be audio_fast_pll
81
*
82
*/
83
84
#define MAX_CLKS 41
85
static struct clk_hw_onecell_data *clk_data;
86
static DEFINE_SPINLOCK(lock);
87
static void __iomem *gbase;
88
89
enum {
90
REFCLK, VIDEO_EXT0,
91
SYSPLL, MEMPLL, CPUPLL,
92
AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
93
AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
94
AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
95
AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
96
AUDIO1_PLL, AUDIO_FAST_PLL,
97
VIDEO0_PLL, VIDEO0_IN,
98
VIDEO1_PLL, VIDEO1_IN,
99
VIDEO2_PLL, VIDEO2_IN,
100
};
101
102
static const char *clk_names[] = {
103
[REFCLK] = "refclk",
104
[VIDEO_EXT0] = "video_ext0",
105
[SYSPLL] = "syspll",
106
[MEMPLL] = "mempll",
107
[CPUPLL] = "cpupll",
108
[AVPLL_A1] = "avpll_a1",
109
[AVPLL_A2] = "avpll_a2",
110
[AVPLL_A3] = "avpll_a3",
111
[AVPLL_A4] = "avpll_a4",
112
[AVPLL_A5] = "avpll_a5",
113
[AVPLL_A6] = "avpll_a6",
114
[AVPLL_A7] = "avpll_a7",
115
[AVPLL_A8] = "avpll_a8",
116
[AVPLL_B1] = "avpll_b1",
117
[AVPLL_B2] = "avpll_b2",
118
[AVPLL_B3] = "avpll_b3",
119
[AVPLL_B4] = "avpll_b4",
120
[AVPLL_B5] = "avpll_b5",
121
[AVPLL_B6] = "avpll_b6",
122
[AVPLL_B7] = "avpll_b7",
123
[AVPLL_B8] = "avpll_b8",
124
[AUDIO1_PLL] = "audio1_pll",
125
[AUDIO_FAST_PLL] = "audio_fast_pll",
126
[VIDEO0_PLL] = "video0_pll",
127
[VIDEO0_IN] = "video0_in",
128
[VIDEO1_PLL] = "video1_pll",
129
[VIDEO1_IN] = "video1_in",
130
[VIDEO2_PLL] = "video2_pll",
131
[VIDEO2_IN] = "video2_in",
132
};
133
134
static const struct berlin2_pll_map bg2_pll_map __initconst = {
135
.vcodiv = {10, 15, 20, 25, 30, 40, 50, 60, 80},
136
.mult = 10,
137
.fbdiv_shift = 6,
138
.rfdiv_shift = 1,
139
.divsel_shift = 7,
140
};
141
142
static const u8 default_parent_ids[] = {
143
SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
144
};
145
146
static const struct berlin2_div_data bg2_divs[] __initconst = {
147
{
148
.name = "sys",
149
.parent_ids = (const u8 []){
150
SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
151
},
152
.num_parents = 6,
153
.map = {
154
BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
155
BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
156
BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
157
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
158
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
159
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
160
},
161
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
162
.flags = CLK_IGNORE_UNUSED,
163
},
164
{
165
.name = "cpu",
166
.parent_ids = (const u8 []){
167
CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
168
},
169
.num_parents = 5,
170
.map = {
171
BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
172
BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
173
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
174
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
175
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
176
},
177
.div_flags = BERLIN2_DIV_HAS_MUX,
178
.flags = 0,
179
},
180
{
181
.name = "drmfigo",
182
.parent_ids = default_parent_ids,
183
.num_parents = ARRAY_SIZE(default_parent_ids),
184
.map = {
185
BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
186
BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
187
BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
188
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
189
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
190
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
191
},
192
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
193
.flags = 0,
194
},
195
{
196
.name = "cfg",
197
.parent_ids = default_parent_ids,
198
.num_parents = ARRAY_SIZE(default_parent_ids),
199
.map = {
200
BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
201
BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
202
BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
203
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
204
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
205
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
206
},
207
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
208
.flags = 0,
209
},
210
{
211
.name = "gfx",
212
.parent_ids = default_parent_ids,
213
.num_parents = ARRAY_SIZE(default_parent_ids),
214
.map = {
215
BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
216
BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
217
BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
218
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
219
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
220
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
221
},
222
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
223
.flags = 0,
224
},
225
{
226
.name = "zsp",
227
.parent_ids = default_parent_ids,
228
.num_parents = ARRAY_SIZE(default_parent_ids),
229
.map = {
230
BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
231
BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
232
BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
233
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
234
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
235
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
236
},
237
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
238
.flags = 0,
239
},
240
{
241
.name = "perif",
242
.parent_ids = default_parent_ids,
243
.num_parents = ARRAY_SIZE(default_parent_ids),
244
.map = {
245
BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
246
BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
247
BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
248
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
249
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
250
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
251
},
252
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
253
.flags = CLK_IGNORE_UNUSED,
254
},
255
{
256
.name = "pcube",
257
.parent_ids = default_parent_ids,
258
.num_parents = ARRAY_SIZE(default_parent_ids),
259
.map = {
260
BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
261
BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
262
BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
263
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
264
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
265
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
266
},
267
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
268
.flags = 0,
269
},
270
{
271
.name = "vscope",
272
.parent_ids = default_parent_ids,
273
.num_parents = ARRAY_SIZE(default_parent_ids),
274
.map = {
275
BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
276
BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
277
BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
278
BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
279
BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
280
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
281
},
282
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
283
.flags = 0,
284
},
285
{
286
.name = "nfc_ecc",
287
.parent_ids = default_parent_ids,
288
.num_parents = ARRAY_SIZE(default_parent_ids),
289
.map = {
290
BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
291
BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
292
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
293
BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
294
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
295
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
296
},
297
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
298
.flags = 0,
299
},
300
{
301
.name = "vpp",
302
.parent_ids = default_parent_ids,
303
.num_parents = ARRAY_SIZE(default_parent_ids),
304
.map = {
305
BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
306
BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
307
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
308
BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
309
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
310
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
311
},
312
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
313
.flags = 0,
314
},
315
{
316
.name = "app",
317
.parent_ids = default_parent_ids,
318
.num_parents = ARRAY_SIZE(default_parent_ids),
319
.map = {
320
BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
321
BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
322
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
323
BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
324
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
325
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
326
},
327
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
328
.flags = 0,
329
},
330
{
331
.name = "audio0",
332
.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
333
.num_parents = 1,
334
.map = {
335
BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
336
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
337
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
338
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
339
},
340
.div_flags = BERLIN2_DIV_HAS_GATE,
341
.flags = 0,
342
},
343
{
344
.name = "audio2",
345
.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
346
.num_parents = 1,
347
.map = {
348
BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
349
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
350
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
351
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
352
},
353
.div_flags = BERLIN2_DIV_HAS_GATE,
354
.flags = 0,
355
},
356
{
357
.name = "audio3",
358
.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
359
.num_parents = 1,
360
.map = {
361
BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
362
BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
363
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
364
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
365
},
366
.div_flags = BERLIN2_DIV_HAS_GATE,
367
.flags = 0,
368
},
369
{
370
.name = "audio1",
371
.parent_ids = (const u8 []){ AUDIO1_PLL },
372
.num_parents = 1,
373
.map = {
374
BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
375
BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
376
BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
377
BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
378
},
379
.div_flags = BERLIN2_DIV_HAS_GATE,
380
.flags = 0,
381
},
382
{
383
.name = "gfx3d_core",
384
.parent_ids = default_parent_ids,
385
.num_parents = ARRAY_SIZE(default_parent_ids),
386
.map = {
387
BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
388
},
389
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
390
.flags = 0,
391
},
392
{
393
.name = "gfx3d_sys",
394
.parent_ids = default_parent_ids,
395
.num_parents = ARRAY_SIZE(default_parent_ids),
396
.map = {
397
BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
398
},
399
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
400
.flags = 0,
401
},
402
{
403
.name = "arc",
404
.parent_ids = default_parent_ids,
405
.num_parents = ARRAY_SIZE(default_parent_ids),
406
.map = {
407
BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
408
},
409
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
410
.flags = 0,
411
},
412
{
413
.name = "vip",
414
.parent_ids = default_parent_ids,
415
.num_parents = ARRAY_SIZE(default_parent_ids),
416
.map = {
417
BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
418
},
419
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
420
.flags = 0,
421
},
422
{
423
.name = "sdio0xin",
424
.parent_ids = default_parent_ids,
425
.num_parents = ARRAY_SIZE(default_parent_ids),
426
.map = {
427
BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
428
},
429
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
430
.flags = 0,
431
},
432
{
433
.name = "sdio1xin",
434
.parent_ids = default_parent_ids,
435
.num_parents = ARRAY_SIZE(default_parent_ids),
436
.map = {
437
BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
438
},
439
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
440
.flags = 0,
441
},
442
{
443
.name = "gfx3d_extra",
444
.parent_ids = default_parent_ids,
445
.num_parents = ARRAY_SIZE(default_parent_ids),
446
.map = {
447
BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
448
},
449
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
450
.flags = 0,
451
},
452
{
453
.name = "gc360",
454
.parent_ids = default_parent_ids,
455
.num_parents = ARRAY_SIZE(default_parent_ids),
456
.map = {
457
BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
458
},
459
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
460
.flags = 0,
461
},
462
{
463
.name = "sdio_dllmst",
464
.parent_ids = default_parent_ids,
465
.num_parents = ARRAY_SIZE(default_parent_ids),
466
.map = {
467
BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
468
},
469
.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
470
.flags = 0,
471
},
472
};
473
474
static const struct berlin2_gate_data bg2_gates[] __initconst = {
475
{ "geth0", "perif", 7 },
476
{ "geth1", "perif", 8 },
477
{ "sata", "perif", 9 },
478
{ "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
479
{ "usb0", "perif", 11 },
480
{ "usb1", "perif", 12 },
481
{ "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
482
{ "sdio0", "perif", 14 },
483
{ "sdio1", "perif", 15 },
484
{ "nfc", "perif", 17 },
485
{ "smemc", "perif", 19 },
486
{ "audiohd", "audiohd_pll", 26 },
487
{ "video0", "video0_in", 27 },
488
{ "video1", "video1_in", 28 },
489
{ "video2", "video2_in", 29 },
490
};
491
492
static void __init berlin2_clock_setup(struct device_node *np)
493
{
494
struct device_node *parent_np = of_get_parent(np);
495
const char *parent_names[9];
496
struct clk *clk;
497
struct clk_hw *hw;
498
struct clk_hw **hws;
499
u8 avpll_flags = 0;
500
int n, ret;
501
502
clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
503
if (!clk_data) {
504
of_node_put(parent_np);
505
return;
506
}
507
clk_data->num = MAX_CLKS;
508
hws = clk_data->hws;
509
510
gbase = of_iomap(parent_np, 0);
511
of_node_put(parent_np);
512
if (!gbase)
513
return;
514
515
/* overwrite default clock names with DT provided ones */
516
clk = of_clk_get_by_name(np, clk_names[REFCLK]);
517
if (!IS_ERR(clk)) {
518
clk_names[REFCLK] = __clk_get_name(clk);
519
clk_put(clk);
520
}
521
522
clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
523
if (!IS_ERR(clk)) {
524
clk_names[VIDEO_EXT0] = __clk_get_name(clk);
525
clk_put(clk);
526
}
527
528
/* simple register PLLs */
529
ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
530
clk_names[SYSPLL], clk_names[REFCLK], 0);
531
if (ret)
532
goto bg2_fail;
533
534
ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
535
clk_names[MEMPLL], clk_names[REFCLK], 0);
536
if (ret)
537
goto bg2_fail;
538
539
ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
540
clk_names[CPUPLL], clk_names[REFCLK], 0);
541
if (ret)
542
goto bg2_fail;
543
544
if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
545
avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
546
547
/* audio/video VCOs */
548
ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
549
clk_names[REFCLK], avpll_flags, 0);
550
if (ret)
551
goto bg2_fail;
552
553
for (n = 0; n < 8; n++) {
554
ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
555
clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
556
avpll_flags, 0);
557
if (ret)
558
goto bg2_fail;
559
}
560
561
ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
562
clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
563
avpll_flags, 0);
564
if (ret)
565
goto bg2_fail;
566
567
for (n = 0; n < 8; n++) {
568
ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
569
clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
570
BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
571
if (ret)
572
goto bg2_fail;
573
}
574
575
/* reference clock bypass switches */
576
parent_names[0] = clk_names[SYSPLL];
577
parent_names[1] = clk_names[REFCLK];
578
hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
579
0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
580
if (IS_ERR(hw))
581
goto bg2_fail;
582
clk_names[SYSPLL] = clk_hw_get_name(hw);
583
584
parent_names[0] = clk_names[MEMPLL];
585
parent_names[1] = clk_names[REFCLK];
586
hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
587
0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
588
if (IS_ERR(hw))
589
goto bg2_fail;
590
clk_names[MEMPLL] = clk_hw_get_name(hw);
591
592
parent_names[0] = clk_names[CPUPLL];
593
parent_names[1] = clk_names[REFCLK];
594
hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
595
0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
596
if (IS_ERR(hw))
597
goto bg2_fail;
598
clk_names[CPUPLL] = clk_hw_get_name(hw);
599
600
/* clock muxes */
601
parent_names[0] = clk_names[AVPLL_B3];
602
parent_names[1] = clk_names[AVPLL_A3];
603
hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
604
0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
605
if (IS_ERR(hw))
606
goto bg2_fail;
607
608
parent_names[0] = clk_names[VIDEO0_PLL];
609
parent_names[1] = clk_names[VIDEO_EXT0];
610
hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
611
0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
612
if (IS_ERR(hw))
613
goto bg2_fail;
614
615
parent_names[0] = clk_names[VIDEO1_PLL];
616
parent_names[1] = clk_names[VIDEO_EXT0];
617
hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
618
0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
619
if (IS_ERR(hw))
620
goto bg2_fail;
621
622
parent_names[0] = clk_names[AVPLL_A2];
623
parent_names[1] = clk_names[AVPLL_B2];
624
hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
625
0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
626
if (IS_ERR(hw))
627
goto bg2_fail;
628
629
parent_names[0] = clk_names[VIDEO2_PLL];
630
parent_names[1] = clk_names[VIDEO_EXT0];
631
hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
632
0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
633
if (IS_ERR(hw))
634
goto bg2_fail;
635
636
parent_names[0] = clk_names[AVPLL_B1];
637
parent_names[1] = clk_names[AVPLL_A5];
638
hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
639
0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
640
if (IS_ERR(hw))
641
goto bg2_fail;
642
643
/* clock divider cells */
644
for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
645
const struct berlin2_div_data *dd = &bg2_divs[n];
646
int k;
647
648
for (k = 0; k < dd->num_parents; k++)
649
parent_names[k] = clk_names[dd->parent_ids[k]];
650
651
hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
652
dd->name, dd->div_flags, parent_names,
653
dd->num_parents, dd->flags, &lock);
654
}
655
656
/* clock gate cells */
657
for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
658
const struct berlin2_gate_data *gd = &bg2_gates[n];
659
660
hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
661
gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
662
gd->bit_idx, 0, &lock);
663
}
664
665
/* twdclk is derived from cpu/3 */
666
hws[CLKID_TWD] =
667
clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
668
669
/* check for errors on leaf clocks */
670
for (n = 0; n < MAX_CLKS; n++) {
671
if (!IS_ERR(hws[n]))
672
continue;
673
674
pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
675
goto bg2_fail;
676
}
677
678
/* register clk-provider */
679
of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
680
681
return;
682
683
bg2_fail:
684
iounmap(gbase);
685
}
686
CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
687
berlin2_clock_setup);
688
689