0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/clk.h>
0010 #include <linux/clk-provider.h>
0011 #include <linux/io.h>
0012 #include <linux/kernel.h>
0013 #include <linux/of.h>
0014 #include <linux/of_address.h>
0015 #include <linux/slab.h>
0016
0017 #include <dt-bindings/clock/berlin2.h>
0018
0019 #include "berlin2-avpll.h"
0020 #include "berlin2-div.h"
0021 #include "berlin2-pll.h"
0022 #include "common.h"
0023
0024 #define REG_PINMUX0 0x0000
0025 #define REG_PINMUX1 0x0004
0026 #define REG_SYSPLLCTL0 0x0014
0027 #define REG_SYSPLLCTL4 0x0024
0028 #define REG_MEMPLLCTL0 0x0028
0029 #define REG_MEMPLLCTL4 0x0038
0030 #define REG_CPUPLLCTL0 0x003c
0031 #define REG_CPUPLLCTL4 0x004c
0032 #define REG_AVPLLCTL0 0x0050
0033 #define REG_AVPLLCTL31 0x00cc
0034 #define REG_AVPLLCTL62 0x0148
0035 #define REG_PLLSTATUS 0x014c
0036 #define REG_CLKENABLE 0x0150
0037 #define REG_CLKSELECT0 0x0154
0038 #define REG_CLKSELECT1 0x0158
0039 #define REG_CLKSELECT2 0x015c
0040 #define REG_CLKSELECT3 0x0160
0041 #define REG_CLKSWITCH0 0x0164
0042 #define REG_CLKSWITCH1 0x0168
0043 #define REG_RESET_TRIGGER 0x0178
0044 #define REG_RESET_STATUS0 0x017c
0045 #define REG_RESET_STATUS1 0x0180
0046 #define REG_SW_GENERIC0 0x0184
0047 #define REG_SW_GENERIC3 0x0190
0048 #define REG_PRODUCTID 0x01cc
0049 #define REG_PRODUCTID_EXT 0x01d0
0050 #define REG_GFX3DCORE_CLKCTL 0x022c
0051 #define REG_GFX3DSYS_CLKCTL 0x0230
0052 #define REG_ARC_CLKCTL 0x0234
0053 #define REG_VIP_CLKCTL 0x0238
0054 #define REG_SDIO0XIN_CLKCTL 0x023c
0055 #define REG_SDIO1XIN_CLKCTL 0x0240
0056 #define REG_GFX3DEXTRA_CLKCTL 0x0244
0057 #define REG_GFX3D_RESET 0x0248
0058 #define REG_GC360_CLKCTL 0x024c
0059 #define REG_SDIO_DLLMST_CLKCTL 0x0250
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084 #define MAX_CLKS 41
0085 static struct clk_hw_onecell_data *clk_data;
0086 static DEFINE_SPINLOCK(lock);
0087 static void __iomem *gbase;
0088
0089 enum {
0090 REFCLK, VIDEO_EXT0,
0091 SYSPLL, MEMPLL, CPUPLL,
0092 AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
0093 AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
0094 AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
0095 AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
0096 AUDIO1_PLL, AUDIO_FAST_PLL,
0097 VIDEO0_PLL, VIDEO0_IN,
0098 VIDEO1_PLL, VIDEO1_IN,
0099 VIDEO2_PLL, VIDEO2_IN,
0100 };
0101
0102 static const char *clk_names[] = {
0103 [REFCLK] = "refclk",
0104 [VIDEO_EXT0] = "video_ext0",
0105 [SYSPLL] = "syspll",
0106 [MEMPLL] = "mempll",
0107 [CPUPLL] = "cpupll",
0108 [AVPLL_A1] = "avpll_a1",
0109 [AVPLL_A2] = "avpll_a2",
0110 [AVPLL_A3] = "avpll_a3",
0111 [AVPLL_A4] = "avpll_a4",
0112 [AVPLL_A5] = "avpll_a5",
0113 [AVPLL_A6] = "avpll_a6",
0114 [AVPLL_A7] = "avpll_a7",
0115 [AVPLL_A8] = "avpll_a8",
0116 [AVPLL_B1] = "avpll_b1",
0117 [AVPLL_B2] = "avpll_b2",
0118 [AVPLL_B3] = "avpll_b3",
0119 [AVPLL_B4] = "avpll_b4",
0120 [AVPLL_B5] = "avpll_b5",
0121 [AVPLL_B6] = "avpll_b6",
0122 [AVPLL_B7] = "avpll_b7",
0123 [AVPLL_B8] = "avpll_b8",
0124 [AUDIO1_PLL] = "audio1_pll",
0125 [AUDIO_FAST_PLL] = "audio_fast_pll",
0126 [VIDEO0_PLL] = "video0_pll",
0127 [VIDEO0_IN] = "video0_in",
0128 [VIDEO1_PLL] = "video1_pll",
0129 [VIDEO1_IN] = "video1_in",
0130 [VIDEO2_PLL] = "video2_pll",
0131 [VIDEO2_IN] = "video2_in",
0132 };
0133
0134 static const struct berlin2_pll_map bg2_pll_map __initconst = {
0135 .vcodiv = {10, 15, 20, 25, 30, 40, 50, 60, 80},
0136 .mult = 10,
0137 .fbdiv_shift = 6,
0138 .rfdiv_shift = 1,
0139 .divsel_shift = 7,
0140 };
0141
0142 static const u8 default_parent_ids[] = {
0143 SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
0144 };
0145
0146 static const struct berlin2_div_data bg2_divs[] __initconst = {
0147 {
0148 .name = "sys",
0149 .parent_ids = (const u8 []){
0150 SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
0151 },
0152 .num_parents = 6,
0153 .map = {
0154 BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
0155 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
0156 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
0157 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
0158 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
0159 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
0160 },
0161 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0162 .flags = CLK_IGNORE_UNUSED,
0163 },
0164 {
0165 .name = "cpu",
0166 .parent_ids = (const u8 []){
0167 CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
0168 },
0169 .num_parents = 5,
0170 .map = {
0171 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
0172 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
0173 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
0174 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
0175 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
0176 },
0177 .div_flags = BERLIN2_DIV_HAS_MUX,
0178 .flags = 0,
0179 },
0180 {
0181 .name = "drmfigo",
0182 .parent_ids = default_parent_ids,
0183 .num_parents = ARRAY_SIZE(default_parent_ids),
0184 .map = {
0185 BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
0186 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
0187 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
0188 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
0189 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
0190 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
0191 },
0192 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0193 .flags = 0,
0194 },
0195 {
0196 .name = "cfg",
0197 .parent_ids = default_parent_ids,
0198 .num_parents = ARRAY_SIZE(default_parent_ids),
0199 .map = {
0200 BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
0201 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
0202 BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
0203 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
0204 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
0205 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
0206 },
0207 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0208 .flags = 0,
0209 },
0210 {
0211 .name = "gfx",
0212 .parent_ids = default_parent_ids,
0213 .num_parents = ARRAY_SIZE(default_parent_ids),
0214 .map = {
0215 BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
0216 BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
0217 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
0218 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
0219 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
0220 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
0221 },
0222 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0223 .flags = 0,
0224 },
0225 {
0226 .name = "zsp",
0227 .parent_ids = default_parent_ids,
0228 .num_parents = ARRAY_SIZE(default_parent_ids),
0229 .map = {
0230 BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
0231 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
0232 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
0233 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
0234 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
0235 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
0236 },
0237 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0238 .flags = 0,
0239 },
0240 {
0241 .name = "perif",
0242 .parent_ids = default_parent_ids,
0243 .num_parents = ARRAY_SIZE(default_parent_ids),
0244 .map = {
0245 BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
0246 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
0247 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
0248 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
0249 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
0250 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
0251 },
0252 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0253 .flags = CLK_IGNORE_UNUSED,
0254 },
0255 {
0256 .name = "pcube",
0257 .parent_ids = default_parent_ids,
0258 .num_parents = ARRAY_SIZE(default_parent_ids),
0259 .map = {
0260 BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
0261 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
0262 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
0263 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
0264 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
0265 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
0266 },
0267 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0268 .flags = 0,
0269 },
0270 {
0271 .name = "vscope",
0272 .parent_ids = default_parent_ids,
0273 .num_parents = ARRAY_SIZE(default_parent_ids),
0274 .map = {
0275 BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
0276 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
0277 BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
0278 BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
0279 BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
0280 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
0281 },
0282 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0283 .flags = 0,
0284 },
0285 {
0286 .name = "nfc_ecc",
0287 .parent_ids = default_parent_ids,
0288 .num_parents = ARRAY_SIZE(default_parent_ids),
0289 .map = {
0290 BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
0291 BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
0292 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
0293 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
0294 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
0295 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
0296 },
0297 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0298 .flags = 0,
0299 },
0300 {
0301 .name = "vpp",
0302 .parent_ids = default_parent_ids,
0303 .num_parents = ARRAY_SIZE(default_parent_ids),
0304 .map = {
0305 BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
0306 BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
0307 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
0308 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
0309 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
0310 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
0311 },
0312 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0313 .flags = 0,
0314 },
0315 {
0316 .name = "app",
0317 .parent_ids = default_parent_ids,
0318 .num_parents = ARRAY_SIZE(default_parent_ids),
0319 .map = {
0320 BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
0321 BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
0322 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
0323 BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
0324 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
0325 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
0326 },
0327 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0328 .flags = 0,
0329 },
0330 {
0331 .name = "audio0",
0332 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
0333 .num_parents = 1,
0334 .map = {
0335 BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
0336 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
0337 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
0338 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
0339 },
0340 .div_flags = BERLIN2_DIV_HAS_GATE,
0341 .flags = 0,
0342 },
0343 {
0344 .name = "audio2",
0345 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
0346 .num_parents = 1,
0347 .map = {
0348 BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
0349 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
0350 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
0351 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
0352 },
0353 .div_flags = BERLIN2_DIV_HAS_GATE,
0354 .flags = 0,
0355 },
0356 {
0357 .name = "audio3",
0358 .parent_ids = (const u8 []){ AUDIO_FAST_PLL },
0359 .num_parents = 1,
0360 .map = {
0361 BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
0362 BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
0363 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
0364 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
0365 },
0366 .div_flags = BERLIN2_DIV_HAS_GATE,
0367 .flags = 0,
0368 },
0369 {
0370 .name = "audio1",
0371 .parent_ids = (const u8 []){ AUDIO1_PLL },
0372 .num_parents = 1,
0373 .map = {
0374 BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
0375 BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
0376 BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
0377 BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
0378 },
0379 .div_flags = BERLIN2_DIV_HAS_GATE,
0380 .flags = 0,
0381 },
0382 {
0383 .name = "gfx3d_core",
0384 .parent_ids = default_parent_ids,
0385 .num_parents = ARRAY_SIZE(default_parent_ids),
0386 .map = {
0387 BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
0388 },
0389 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0390 .flags = 0,
0391 },
0392 {
0393 .name = "gfx3d_sys",
0394 .parent_ids = default_parent_ids,
0395 .num_parents = ARRAY_SIZE(default_parent_ids),
0396 .map = {
0397 BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
0398 },
0399 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0400 .flags = 0,
0401 },
0402 {
0403 .name = "arc",
0404 .parent_ids = default_parent_ids,
0405 .num_parents = ARRAY_SIZE(default_parent_ids),
0406 .map = {
0407 BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
0408 },
0409 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0410 .flags = 0,
0411 },
0412 {
0413 .name = "vip",
0414 .parent_ids = default_parent_ids,
0415 .num_parents = ARRAY_SIZE(default_parent_ids),
0416 .map = {
0417 BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
0418 },
0419 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0420 .flags = 0,
0421 },
0422 {
0423 .name = "sdio0xin",
0424 .parent_ids = default_parent_ids,
0425 .num_parents = ARRAY_SIZE(default_parent_ids),
0426 .map = {
0427 BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
0428 },
0429 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0430 .flags = 0,
0431 },
0432 {
0433 .name = "sdio1xin",
0434 .parent_ids = default_parent_ids,
0435 .num_parents = ARRAY_SIZE(default_parent_ids),
0436 .map = {
0437 BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
0438 },
0439 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0440 .flags = 0,
0441 },
0442 {
0443 .name = "gfx3d_extra",
0444 .parent_ids = default_parent_ids,
0445 .num_parents = ARRAY_SIZE(default_parent_ids),
0446 .map = {
0447 BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
0448 },
0449 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0450 .flags = 0,
0451 },
0452 {
0453 .name = "gc360",
0454 .parent_ids = default_parent_ids,
0455 .num_parents = ARRAY_SIZE(default_parent_ids),
0456 .map = {
0457 BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
0458 },
0459 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0460 .flags = 0,
0461 },
0462 {
0463 .name = "sdio_dllmst",
0464 .parent_ids = default_parent_ids,
0465 .num_parents = ARRAY_SIZE(default_parent_ids),
0466 .map = {
0467 BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
0468 },
0469 .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
0470 .flags = 0,
0471 },
0472 };
0473
0474 static const struct berlin2_gate_data bg2_gates[] __initconst = {
0475 { "geth0", "perif", 7 },
0476 { "geth1", "perif", 8 },
0477 { "sata", "perif", 9 },
0478 { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
0479 { "usb0", "perif", 11 },
0480 { "usb1", "perif", 12 },
0481 { "pbridge", "perif", 13, CLK_IGNORE_UNUSED },
0482 { "sdio0", "perif", 14 },
0483 { "sdio1", "perif", 15 },
0484 { "nfc", "perif", 17 },
0485 { "smemc", "perif", 19 },
0486 { "audiohd", "audiohd_pll", 26 },
0487 { "video0", "video0_in", 27 },
0488 { "video1", "video1_in", 28 },
0489 { "video2", "video2_in", 29 },
0490 };
0491
0492 static void __init berlin2_clock_setup(struct device_node *np)
0493 {
0494 struct device_node *parent_np = of_get_parent(np);
0495 const char *parent_names[9];
0496 struct clk *clk;
0497 struct clk_hw *hw;
0498 struct clk_hw **hws;
0499 u8 avpll_flags = 0;
0500 int n, ret;
0501
0502 clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
0503 if (!clk_data)
0504 return;
0505 clk_data->num = MAX_CLKS;
0506 hws = clk_data->hws;
0507
0508 gbase = of_iomap(parent_np, 0);
0509 if (!gbase)
0510 return;
0511
0512
0513 clk = of_clk_get_by_name(np, clk_names[REFCLK]);
0514 if (!IS_ERR(clk)) {
0515 clk_names[REFCLK] = __clk_get_name(clk);
0516 clk_put(clk);
0517 }
0518
0519 clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
0520 if (!IS_ERR(clk)) {
0521 clk_names[VIDEO_EXT0] = __clk_get_name(clk);
0522 clk_put(clk);
0523 }
0524
0525
0526 ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
0527 clk_names[SYSPLL], clk_names[REFCLK], 0);
0528 if (ret)
0529 goto bg2_fail;
0530
0531 ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
0532 clk_names[MEMPLL], clk_names[REFCLK], 0);
0533 if (ret)
0534 goto bg2_fail;
0535
0536 ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
0537 clk_names[CPUPLL], clk_names[REFCLK], 0);
0538 if (ret)
0539 goto bg2_fail;
0540
0541 if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
0542 avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
0543
0544
0545 ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
0546 clk_names[REFCLK], avpll_flags, 0);
0547 if (ret)
0548 goto bg2_fail;
0549
0550 for (n = 0; n < 8; n++) {
0551 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
0552 clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
0553 avpll_flags, 0);
0554 if (ret)
0555 goto bg2_fail;
0556 }
0557
0558 ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
0559 clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
0560 avpll_flags, 0);
0561 if (ret)
0562 goto bg2_fail;
0563
0564 for (n = 0; n < 8; n++) {
0565 ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
0566 clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
0567 BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
0568 if (ret)
0569 goto bg2_fail;
0570 }
0571
0572
0573 parent_names[0] = clk_names[SYSPLL];
0574 parent_names[1] = clk_names[REFCLK];
0575 hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
0576 0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
0577 if (IS_ERR(hw))
0578 goto bg2_fail;
0579 clk_names[SYSPLL] = clk_hw_get_name(hw);
0580
0581 parent_names[0] = clk_names[MEMPLL];
0582 parent_names[1] = clk_names[REFCLK];
0583 hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
0584 0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
0585 if (IS_ERR(hw))
0586 goto bg2_fail;
0587 clk_names[MEMPLL] = clk_hw_get_name(hw);
0588
0589 parent_names[0] = clk_names[CPUPLL];
0590 parent_names[1] = clk_names[REFCLK];
0591 hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
0592 0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
0593 if (IS_ERR(hw))
0594 goto bg2_fail;
0595 clk_names[CPUPLL] = clk_hw_get_name(hw);
0596
0597
0598 parent_names[0] = clk_names[AVPLL_B3];
0599 parent_names[1] = clk_names[AVPLL_A3];
0600 hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
0601 0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
0602 if (IS_ERR(hw))
0603 goto bg2_fail;
0604
0605 parent_names[0] = clk_names[VIDEO0_PLL];
0606 parent_names[1] = clk_names[VIDEO_EXT0];
0607 hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
0608 0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
0609 if (IS_ERR(hw))
0610 goto bg2_fail;
0611
0612 parent_names[0] = clk_names[VIDEO1_PLL];
0613 parent_names[1] = clk_names[VIDEO_EXT0];
0614 hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
0615 0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
0616 if (IS_ERR(hw))
0617 goto bg2_fail;
0618
0619 parent_names[0] = clk_names[AVPLL_A2];
0620 parent_names[1] = clk_names[AVPLL_B2];
0621 hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
0622 0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
0623 if (IS_ERR(hw))
0624 goto bg2_fail;
0625
0626 parent_names[0] = clk_names[VIDEO2_PLL];
0627 parent_names[1] = clk_names[VIDEO_EXT0];
0628 hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
0629 0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
0630 if (IS_ERR(hw))
0631 goto bg2_fail;
0632
0633 parent_names[0] = clk_names[AVPLL_B1];
0634 parent_names[1] = clk_names[AVPLL_A5];
0635 hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
0636 0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
0637 if (IS_ERR(hw))
0638 goto bg2_fail;
0639
0640
0641 for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
0642 const struct berlin2_div_data *dd = &bg2_divs[n];
0643 int k;
0644
0645 for (k = 0; k < dd->num_parents; k++)
0646 parent_names[k] = clk_names[dd->parent_ids[k]];
0647
0648 hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
0649 dd->name, dd->div_flags, parent_names,
0650 dd->num_parents, dd->flags, &lock);
0651 }
0652
0653
0654 for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
0655 const struct berlin2_gate_data *gd = &bg2_gates[n];
0656
0657 hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
0658 gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
0659 gd->bit_idx, 0, &lock);
0660 }
0661
0662
0663 hws[CLKID_TWD] =
0664 clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
0665
0666
0667 for (n = 0; n < MAX_CLKS; n++) {
0668 if (!IS_ERR(hws[n]))
0669 continue;
0670
0671 pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
0672 goto bg2_fail;
0673 }
0674
0675
0676 of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
0677
0678 return;
0679
0680 bg2_fail:
0681 iounmap(gbase);
0682 }
0683 CLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
0684 berlin2_clock_setup);