Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2014 Marvell Technology Group Ltd.
0004  *
0005  * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
0006  * Alexandre Belloni <alexandre.belloni@free-electrons.com>
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  * BG2/BG2CD SoCs have the following audio/video I/O units:
0063  *
0064  * audiohd: HDMI TX audio
0065  * audio0:  7.1ch TX
0066  * audio1:  2ch TX
0067  * audio2:  2ch RX
0068  * audio3:  SPDIF TX
0069  * video0:  HDMI video
0070  * video1:  Secondary video
0071  * video2:  SD auxiliary video
0072  *
0073  * There are no external audio clocks (ACLKI0, ACLKI1) and
0074  * only one external video clock (VCLKI0).
0075  *
0076  * Currently missing bits and pieces:
0077  * - audio_fast_pll is unknown
0078  * - audiohd_pll is unknown
0079  * - video0_pll is unknown
0080  * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
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     /* overwrite default clock names with DT provided ones */
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     /* simple register PLLs */
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     /* audio/video VCOs */
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     /* reference clock bypass switches */
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     /* clock muxes */
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     /* clock divider cells */
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     /* clock gate cells */
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     /* twdclk is derived from cpu/3 */
0663     hws[CLKID_TWD] =
0664         clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
0665 
0666     /* check for errors on leaf clocks */
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     /* register clk-provider */
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);