162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014 Marvell Technology Group Ltd.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
662306a36Sopenharmony_ci * Alexandre Belloni <alexandre.belloni@free-electrons.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <linux/clk.h>
1062306a36Sopenharmony_ci#include <linux/clk-provider.h>
1162306a36Sopenharmony_ci#include <linux/io.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/of.h>
1462306a36Sopenharmony_ci#include <linux/of_address.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci#include <dt-bindings/clock/berlin2.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "berlin2-avpll.h"
2062306a36Sopenharmony_ci#include "berlin2-div.h"
2162306a36Sopenharmony_ci#include "berlin2-pll.h"
2262306a36Sopenharmony_ci#include "common.h"
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define REG_PINMUX0		0x0000
2562306a36Sopenharmony_ci#define REG_PINMUX1		0x0004
2662306a36Sopenharmony_ci#define REG_SYSPLLCTL0		0x0014
2762306a36Sopenharmony_ci#define REG_SYSPLLCTL4		0x0024
2862306a36Sopenharmony_ci#define REG_MEMPLLCTL0		0x0028
2962306a36Sopenharmony_ci#define REG_MEMPLLCTL4		0x0038
3062306a36Sopenharmony_ci#define REG_CPUPLLCTL0		0x003c
3162306a36Sopenharmony_ci#define REG_CPUPLLCTL4		0x004c
3262306a36Sopenharmony_ci#define REG_AVPLLCTL0		0x0050
3362306a36Sopenharmony_ci#define REG_AVPLLCTL31		0x00cc
3462306a36Sopenharmony_ci#define REG_AVPLLCTL62		0x0148
3562306a36Sopenharmony_ci#define REG_PLLSTATUS		0x014c
3662306a36Sopenharmony_ci#define REG_CLKENABLE		0x0150
3762306a36Sopenharmony_ci#define REG_CLKSELECT0		0x0154
3862306a36Sopenharmony_ci#define REG_CLKSELECT1		0x0158
3962306a36Sopenharmony_ci#define REG_CLKSELECT2		0x015c
4062306a36Sopenharmony_ci#define REG_CLKSELECT3		0x0160
4162306a36Sopenharmony_ci#define REG_CLKSWITCH0		0x0164
4262306a36Sopenharmony_ci#define REG_CLKSWITCH1		0x0168
4362306a36Sopenharmony_ci#define REG_RESET_TRIGGER	0x0178
4462306a36Sopenharmony_ci#define REG_RESET_STATUS0	0x017c
4562306a36Sopenharmony_ci#define REG_RESET_STATUS1	0x0180
4662306a36Sopenharmony_ci#define REG_SW_GENERIC0		0x0184
4762306a36Sopenharmony_ci#define REG_SW_GENERIC3		0x0190
4862306a36Sopenharmony_ci#define REG_PRODUCTID		0x01cc
4962306a36Sopenharmony_ci#define REG_PRODUCTID_EXT	0x01d0
5062306a36Sopenharmony_ci#define REG_GFX3DCORE_CLKCTL	0x022c
5162306a36Sopenharmony_ci#define REG_GFX3DSYS_CLKCTL	0x0230
5262306a36Sopenharmony_ci#define REG_ARC_CLKCTL		0x0234
5362306a36Sopenharmony_ci#define REG_VIP_CLKCTL		0x0238
5462306a36Sopenharmony_ci#define REG_SDIO0XIN_CLKCTL	0x023c
5562306a36Sopenharmony_ci#define REG_SDIO1XIN_CLKCTL	0x0240
5662306a36Sopenharmony_ci#define REG_GFX3DEXTRA_CLKCTL	0x0244
5762306a36Sopenharmony_ci#define REG_GFX3D_RESET		0x0248
5862306a36Sopenharmony_ci#define REG_GC360_CLKCTL	0x024c
5962306a36Sopenharmony_ci#define REG_SDIO_DLLMST_CLKCTL	0x0250
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*
6262306a36Sopenharmony_ci * BG2/BG2CD SoCs have the following audio/video I/O units:
6362306a36Sopenharmony_ci *
6462306a36Sopenharmony_ci * audiohd: HDMI TX audio
6562306a36Sopenharmony_ci * audio0:  7.1ch TX
6662306a36Sopenharmony_ci * audio1:  2ch TX
6762306a36Sopenharmony_ci * audio2:  2ch RX
6862306a36Sopenharmony_ci * audio3:  SPDIF TX
6962306a36Sopenharmony_ci * video0:  HDMI video
7062306a36Sopenharmony_ci * video1:  Secondary video
7162306a36Sopenharmony_ci * video2:  SD auxiliary video
7262306a36Sopenharmony_ci *
7362306a36Sopenharmony_ci * There are no external audio clocks (ACLKI0, ACLKI1) and
7462306a36Sopenharmony_ci * only one external video clock (VCLKI0).
7562306a36Sopenharmony_ci *
7662306a36Sopenharmony_ci * Currently missing bits and pieces:
7762306a36Sopenharmony_ci * - audio_fast_pll is unknown
7862306a36Sopenharmony_ci * - audiohd_pll is unknown
7962306a36Sopenharmony_ci * - video0_pll is unknown
8062306a36Sopenharmony_ci * - audio[023], audiohd parent pll is assumed to be audio_fast_pll
8162306a36Sopenharmony_ci *
8262306a36Sopenharmony_ci */
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci#define	MAX_CLKS 41
8562306a36Sopenharmony_cistatic struct clk_hw_onecell_data *clk_data;
8662306a36Sopenharmony_cistatic DEFINE_SPINLOCK(lock);
8762306a36Sopenharmony_cistatic void __iomem *gbase;
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cienum {
9062306a36Sopenharmony_ci	REFCLK, VIDEO_EXT0,
9162306a36Sopenharmony_ci	SYSPLL, MEMPLL, CPUPLL,
9262306a36Sopenharmony_ci	AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4,
9362306a36Sopenharmony_ci	AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8,
9462306a36Sopenharmony_ci	AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
9562306a36Sopenharmony_ci	AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
9662306a36Sopenharmony_ci	AUDIO1_PLL, AUDIO_FAST_PLL,
9762306a36Sopenharmony_ci	VIDEO0_PLL, VIDEO0_IN,
9862306a36Sopenharmony_ci	VIDEO1_PLL, VIDEO1_IN,
9962306a36Sopenharmony_ci	VIDEO2_PLL, VIDEO2_IN,
10062306a36Sopenharmony_ci};
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_cistatic const char *clk_names[] = {
10362306a36Sopenharmony_ci	[REFCLK]		= "refclk",
10462306a36Sopenharmony_ci	[VIDEO_EXT0]		= "video_ext0",
10562306a36Sopenharmony_ci	[SYSPLL]		= "syspll",
10662306a36Sopenharmony_ci	[MEMPLL]		= "mempll",
10762306a36Sopenharmony_ci	[CPUPLL]		= "cpupll",
10862306a36Sopenharmony_ci	[AVPLL_A1]		= "avpll_a1",
10962306a36Sopenharmony_ci	[AVPLL_A2]		= "avpll_a2",
11062306a36Sopenharmony_ci	[AVPLL_A3]		= "avpll_a3",
11162306a36Sopenharmony_ci	[AVPLL_A4]		= "avpll_a4",
11262306a36Sopenharmony_ci	[AVPLL_A5]		= "avpll_a5",
11362306a36Sopenharmony_ci	[AVPLL_A6]		= "avpll_a6",
11462306a36Sopenharmony_ci	[AVPLL_A7]		= "avpll_a7",
11562306a36Sopenharmony_ci	[AVPLL_A8]		= "avpll_a8",
11662306a36Sopenharmony_ci	[AVPLL_B1]		= "avpll_b1",
11762306a36Sopenharmony_ci	[AVPLL_B2]		= "avpll_b2",
11862306a36Sopenharmony_ci	[AVPLL_B3]		= "avpll_b3",
11962306a36Sopenharmony_ci	[AVPLL_B4]		= "avpll_b4",
12062306a36Sopenharmony_ci	[AVPLL_B5]		= "avpll_b5",
12162306a36Sopenharmony_ci	[AVPLL_B6]		= "avpll_b6",
12262306a36Sopenharmony_ci	[AVPLL_B7]		= "avpll_b7",
12362306a36Sopenharmony_ci	[AVPLL_B8]		= "avpll_b8",
12462306a36Sopenharmony_ci	[AUDIO1_PLL]		= "audio1_pll",
12562306a36Sopenharmony_ci	[AUDIO_FAST_PLL]	= "audio_fast_pll",
12662306a36Sopenharmony_ci	[VIDEO0_PLL]		= "video0_pll",
12762306a36Sopenharmony_ci	[VIDEO0_IN]		= "video0_in",
12862306a36Sopenharmony_ci	[VIDEO1_PLL]		= "video1_pll",
12962306a36Sopenharmony_ci	[VIDEO1_IN]		= "video1_in",
13062306a36Sopenharmony_ci	[VIDEO2_PLL]		= "video2_pll",
13162306a36Sopenharmony_ci	[VIDEO2_IN]		= "video2_in",
13262306a36Sopenharmony_ci};
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_cistatic const struct berlin2_pll_map bg2_pll_map __initconst = {
13562306a36Sopenharmony_ci	.vcodiv		= {10, 15, 20, 25, 30, 40, 50, 60, 80},
13662306a36Sopenharmony_ci	.mult		= 10,
13762306a36Sopenharmony_ci	.fbdiv_shift	= 6,
13862306a36Sopenharmony_ci	.rfdiv_shift	= 1,
13962306a36Sopenharmony_ci	.divsel_shift	= 7,
14062306a36Sopenharmony_ci};
14162306a36Sopenharmony_ci
14262306a36Sopenharmony_cistatic const u8 default_parent_ids[] = {
14362306a36Sopenharmony_ci	SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic const struct berlin2_div_data bg2_divs[] __initconst = {
14762306a36Sopenharmony_ci	{
14862306a36Sopenharmony_ci		.name = "sys",
14962306a36Sopenharmony_ci		.parent_ids = (const u8 []){
15062306a36Sopenharmony_ci			SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
15162306a36Sopenharmony_ci		},
15262306a36Sopenharmony_ci		.num_parents = 6,
15362306a36Sopenharmony_ci		.map = {
15462306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
15562306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
15662306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
15762306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
15862306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
15962306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
16062306a36Sopenharmony_ci		},
16162306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
16262306a36Sopenharmony_ci		.flags = CLK_IGNORE_UNUSED,
16362306a36Sopenharmony_ci	},
16462306a36Sopenharmony_ci	{
16562306a36Sopenharmony_ci		.name = "cpu",
16662306a36Sopenharmony_ci		.parent_ids = (const u8 []){
16762306a36Sopenharmony_ci			CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL
16862306a36Sopenharmony_ci		},
16962306a36Sopenharmony_ci		.num_parents = 5,
17062306a36Sopenharmony_ci		.map = {
17162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
17262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
17362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
17462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
17562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
17662306a36Sopenharmony_ci		},
17762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_MUX,
17862306a36Sopenharmony_ci		.flags = 0,
17962306a36Sopenharmony_ci	},
18062306a36Sopenharmony_ci	{
18162306a36Sopenharmony_ci		.name = "drmfigo",
18262306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
18362306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
18462306a36Sopenharmony_ci		.map = {
18562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 16),
18662306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17),
18762306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20),
18862306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
18962306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
19062306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
19162306a36Sopenharmony_ci		},
19262306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
19362306a36Sopenharmony_ci		.flags = 0,
19462306a36Sopenharmony_ci	},
19562306a36Sopenharmony_ci	{
19662306a36Sopenharmony_ci		.name = "cfg",
19762306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
19862306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
19962306a36Sopenharmony_ci		.map = {
20062306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
20162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23),
20262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26),
20362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
20462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
20562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
20662306a36Sopenharmony_ci		},
20762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
20862306a36Sopenharmony_ci		.flags = 0,
20962306a36Sopenharmony_ci	},
21062306a36Sopenharmony_ci	{
21162306a36Sopenharmony_ci		.name = "gfx",
21262306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
21362306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
21462306a36Sopenharmony_ci		.map = {
21562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
21662306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29),
21762306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0),
21862306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
21962306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
22062306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
22162306a36Sopenharmony_ci		},
22262306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
22362306a36Sopenharmony_ci		.flags = 0,
22462306a36Sopenharmony_ci	},
22562306a36Sopenharmony_ci	{
22662306a36Sopenharmony_ci		.name = "zsp",
22762306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
22862306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
22962306a36Sopenharmony_ci		.map = {
23062306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 5),
23162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3),
23262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6),
23362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
23462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
23562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
23662306a36Sopenharmony_ci		},
23762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
23862306a36Sopenharmony_ci		.flags = 0,
23962306a36Sopenharmony_ci	},
24062306a36Sopenharmony_ci	{
24162306a36Sopenharmony_ci		.name = "perif",
24262306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
24362306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
24462306a36Sopenharmony_ci		.map = {
24562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
24662306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9),
24762306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12),
24862306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
24962306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
25062306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
25162306a36Sopenharmony_ci		},
25262306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
25362306a36Sopenharmony_ci		.flags = CLK_IGNORE_UNUSED,
25462306a36Sopenharmony_ci	},
25562306a36Sopenharmony_ci	{
25662306a36Sopenharmony_ci		.name = "pcube",
25762306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
25862306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
25962306a36Sopenharmony_ci		.map = {
26062306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
26162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15),
26262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18),
26362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
26462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
26562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
26662306a36Sopenharmony_ci		},
26762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
26862306a36Sopenharmony_ci		.flags = 0,
26962306a36Sopenharmony_ci	},
27062306a36Sopenharmony_ci	{
27162306a36Sopenharmony_ci		.name = "vscope",
27262306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
27362306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
27462306a36Sopenharmony_ci		.map = {
27562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
27662306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21),
27762306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24),
27862306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
27962306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
28062306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
28162306a36Sopenharmony_ci		},
28262306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
28362306a36Sopenharmony_ci		.flags = 0,
28462306a36Sopenharmony_ci	},
28562306a36Sopenharmony_ci	{
28662306a36Sopenharmony_ci		.name = "nfc_ecc",
28762306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
28862306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
28962306a36Sopenharmony_ci		.map = {
29062306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 18),
29162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27),
29262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0),
29362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
29462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
29562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
29662306a36Sopenharmony_ci		},
29762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
29862306a36Sopenharmony_ci		.flags = 0,
29962306a36Sopenharmony_ci	},
30062306a36Sopenharmony_ci	{
30162306a36Sopenharmony_ci		.name = "vpp",
30262306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
30362306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
30462306a36Sopenharmony_ci		.map = {
30562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
30662306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3),
30762306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6),
30862306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4),
30962306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5),
31062306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6),
31162306a36Sopenharmony_ci		},
31262306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
31362306a36Sopenharmony_ci		.flags = 0,
31462306a36Sopenharmony_ci	},
31562306a36Sopenharmony_ci	{
31662306a36Sopenharmony_ci		.name = "app",
31762306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
31862306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
31962306a36Sopenharmony_ci		.map = {
32062306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
32162306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9),
32262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12),
32362306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7),
32462306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8),
32562306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9),
32662306a36Sopenharmony_ci		},
32762306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
32862306a36Sopenharmony_ci		.flags = 0,
32962306a36Sopenharmony_ci	},
33062306a36Sopenharmony_ci	{
33162306a36Sopenharmony_ci		.name = "audio0",
33262306a36Sopenharmony_ci		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
33362306a36Sopenharmony_ci		.num_parents = 1,
33462306a36Sopenharmony_ci		.map = {
33562306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 22),
33662306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17),
33762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10),
33862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11),
33962306a36Sopenharmony_ci		},
34062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE,
34162306a36Sopenharmony_ci		.flags = 0,
34262306a36Sopenharmony_ci	},
34362306a36Sopenharmony_ci	{
34462306a36Sopenharmony_ci		.name = "audio2",
34562306a36Sopenharmony_ci		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
34662306a36Sopenharmony_ci		.num_parents = 1,
34762306a36Sopenharmony_ci		.map = {
34862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 24),
34962306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20),
35062306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14),
35162306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15),
35262306a36Sopenharmony_ci		},
35362306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE,
35462306a36Sopenharmony_ci		.flags = 0,
35562306a36Sopenharmony_ci	},
35662306a36Sopenharmony_ci	{
35762306a36Sopenharmony_ci		.name = "audio3",
35862306a36Sopenharmony_ci		.parent_ids = (const u8 []){ AUDIO_FAST_PLL },
35962306a36Sopenharmony_ci		.num_parents = 1,
36062306a36Sopenharmony_ci		.map = {
36162306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 25),
36262306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23),
36362306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16),
36462306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17),
36562306a36Sopenharmony_ci		},
36662306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE,
36762306a36Sopenharmony_ci		.flags = 0,
36862306a36Sopenharmony_ci	},
36962306a36Sopenharmony_ci	{
37062306a36Sopenharmony_ci		.name = "audio1",
37162306a36Sopenharmony_ci		.parent_ids = (const u8 []){ AUDIO1_PLL },
37262306a36Sopenharmony_ci		.num_parents = 1,
37362306a36Sopenharmony_ci		.map = {
37462306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 23),
37562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0),
37662306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12),
37762306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13),
37862306a36Sopenharmony_ci		},
37962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE,
38062306a36Sopenharmony_ci		.flags = 0,
38162306a36Sopenharmony_ci	},
38262306a36Sopenharmony_ci	{
38362306a36Sopenharmony_ci		.name = "gfx3d_core",
38462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
38562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
38662306a36Sopenharmony_ci		.map = {
38762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL),
38862306a36Sopenharmony_ci		},
38962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
39062306a36Sopenharmony_ci		.flags = 0,
39162306a36Sopenharmony_ci	},
39262306a36Sopenharmony_ci	{
39362306a36Sopenharmony_ci		.name = "gfx3d_sys",
39462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
39562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
39662306a36Sopenharmony_ci		.map = {
39762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL),
39862306a36Sopenharmony_ci		},
39962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
40062306a36Sopenharmony_ci		.flags = 0,
40162306a36Sopenharmony_ci	},
40262306a36Sopenharmony_ci	{
40362306a36Sopenharmony_ci		.name = "arc",
40462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
40562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
40662306a36Sopenharmony_ci		.map = {
40762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL),
40862306a36Sopenharmony_ci		},
40962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
41062306a36Sopenharmony_ci		.flags = 0,
41162306a36Sopenharmony_ci	},
41262306a36Sopenharmony_ci	{
41362306a36Sopenharmony_ci		.name = "vip",
41462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
41562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
41662306a36Sopenharmony_ci		.map = {
41762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL),
41862306a36Sopenharmony_ci		},
41962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
42062306a36Sopenharmony_ci		.flags = 0,
42162306a36Sopenharmony_ci	},
42262306a36Sopenharmony_ci	{
42362306a36Sopenharmony_ci		.name = "sdio0xin",
42462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
42562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
42662306a36Sopenharmony_ci		.map = {
42762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
42862306a36Sopenharmony_ci		},
42962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
43062306a36Sopenharmony_ci		.flags = 0,
43162306a36Sopenharmony_ci	},
43262306a36Sopenharmony_ci	{
43362306a36Sopenharmony_ci		.name = "sdio1xin",
43462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
43562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
43662306a36Sopenharmony_ci		.map = {
43762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
43862306a36Sopenharmony_ci		},
43962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
44062306a36Sopenharmony_ci		.flags = 0,
44162306a36Sopenharmony_ci	},
44262306a36Sopenharmony_ci	{
44362306a36Sopenharmony_ci		.name = "gfx3d_extra",
44462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
44562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
44662306a36Sopenharmony_ci		.map = {
44762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL),
44862306a36Sopenharmony_ci		},
44962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
45062306a36Sopenharmony_ci		.flags = 0,
45162306a36Sopenharmony_ci	},
45262306a36Sopenharmony_ci	{
45362306a36Sopenharmony_ci		.name = "gc360",
45462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
45562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
45662306a36Sopenharmony_ci		.map = {
45762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL),
45862306a36Sopenharmony_ci		},
45962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
46062306a36Sopenharmony_ci		.flags = 0,
46162306a36Sopenharmony_ci	},
46262306a36Sopenharmony_ci	{
46362306a36Sopenharmony_ci		.name = "sdio_dllmst",
46462306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
46562306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
46662306a36Sopenharmony_ci		.map = {
46762306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL),
46862306a36Sopenharmony_ci		},
46962306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
47062306a36Sopenharmony_ci		.flags = 0,
47162306a36Sopenharmony_ci	},
47262306a36Sopenharmony_ci};
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_cistatic const struct berlin2_gate_data bg2_gates[] __initconst = {
47562306a36Sopenharmony_ci	{ "geth0",	"perif",	7 },
47662306a36Sopenharmony_ci	{ "geth1",	"perif",	8 },
47762306a36Sopenharmony_ci	{ "sata",	"perif",	9 },
47862306a36Sopenharmony_ci	{ "ahbapb",	"perif",	10, CLK_IGNORE_UNUSED },
47962306a36Sopenharmony_ci	{ "usb0",	"perif",	11 },
48062306a36Sopenharmony_ci	{ "usb1",	"perif",	12 },
48162306a36Sopenharmony_ci	{ "pbridge",	"perif",	13, CLK_IGNORE_UNUSED },
48262306a36Sopenharmony_ci	{ "sdio0",	"perif",	14 },
48362306a36Sopenharmony_ci	{ "sdio1",	"perif",	15 },
48462306a36Sopenharmony_ci	{ "nfc",	"perif",	17 },
48562306a36Sopenharmony_ci	{ "smemc",	"perif",	19 },
48662306a36Sopenharmony_ci	{ "audiohd",	"audiohd_pll",	26 },
48762306a36Sopenharmony_ci	{ "video0",	"video0_in",	27 },
48862306a36Sopenharmony_ci	{ "video1",	"video1_in",	28 },
48962306a36Sopenharmony_ci	{ "video2",	"video2_in",	29 },
49062306a36Sopenharmony_ci};
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_cistatic void __init berlin2_clock_setup(struct device_node *np)
49362306a36Sopenharmony_ci{
49462306a36Sopenharmony_ci	struct device_node *parent_np = of_get_parent(np);
49562306a36Sopenharmony_ci	const char *parent_names[9];
49662306a36Sopenharmony_ci	struct clk *clk;
49762306a36Sopenharmony_ci	struct clk_hw *hw;
49862306a36Sopenharmony_ci	struct clk_hw **hws;
49962306a36Sopenharmony_ci	u8 avpll_flags = 0;
50062306a36Sopenharmony_ci	int n, ret;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
50362306a36Sopenharmony_ci	if (!clk_data) {
50462306a36Sopenharmony_ci		of_node_put(parent_np);
50562306a36Sopenharmony_ci		return;
50662306a36Sopenharmony_ci	}
50762306a36Sopenharmony_ci	clk_data->num = MAX_CLKS;
50862306a36Sopenharmony_ci	hws = clk_data->hws;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci	gbase = of_iomap(parent_np, 0);
51162306a36Sopenharmony_ci	of_node_put(parent_np);
51262306a36Sopenharmony_ci	if (!gbase)
51362306a36Sopenharmony_ci		return;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	/* overwrite default clock names with DT provided ones */
51662306a36Sopenharmony_ci	clk = of_clk_get_by_name(np, clk_names[REFCLK]);
51762306a36Sopenharmony_ci	if (!IS_ERR(clk)) {
51862306a36Sopenharmony_ci		clk_names[REFCLK] = __clk_get_name(clk);
51962306a36Sopenharmony_ci		clk_put(clk);
52062306a36Sopenharmony_ci	}
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]);
52362306a36Sopenharmony_ci	if (!IS_ERR(clk)) {
52462306a36Sopenharmony_ci		clk_names[VIDEO_EXT0] = __clk_get_name(clk);
52562306a36Sopenharmony_ci		clk_put(clk);
52662306a36Sopenharmony_ci	}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	/* simple register PLLs */
52962306a36Sopenharmony_ci	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0,
53062306a36Sopenharmony_ci				   clk_names[SYSPLL], clk_names[REFCLK], 0);
53162306a36Sopenharmony_ci	if (ret)
53262306a36Sopenharmony_ci		goto bg2_fail;
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0,
53562306a36Sopenharmony_ci				   clk_names[MEMPLL], clk_names[REFCLK], 0);
53662306a36Sopenharmony_ci	if (ret)
53762306a36Sopenharmony_ci		goto bg2_fail;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0,
54062306a36Sopenharmony_ci				   clk_names[CPUPLL], clk_names[REFCLK], 0);
54162306a36Sopenharmony_ci	if (ret)
54262306a36Sopenharmony_ci		goto bg2_fail;
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	if (of_device_is_compatible(np, "marvell,berlin2-global-register"))
54562306a36Sopenharmony_ci		avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK;
54662306a36Sopenharmony_ci
54762306a36Sopenharmony_ci	/* audio/video VCOs */
54862306a36Sopenharmony_ci	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA",
54962306a36Sopenharmony_ci			 clk_names[REFCLK], avpll_flags, 0);
55062306a36Sopenharmony_ci	if (ret)
55162306a36Sopenharmony_ci		goto bg2_fail;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	for (n = 0; n < 8; n++) {
55462306a36Sopenharmony_ci		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0,
55562306a36Sopenharmony_ci			     clk_names[AVPLL_A1 + n], n, "avpll_vcoA",
55662306a36Sopenharmony_ci			     avpll_flags, 0);
55762306a36Sopenharmony_ci		if (ret)
55862306a36Sopenharmony_ci			goto bg2_fail;
55962306a36Sopenharmony_ci	}
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB",
56262306a36Sopenharmony_ci				 clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK |
56362306a36Sopenharmony_ci				 avpll_flags, 0);
56462306a36Sopenharmony_ci	if (ret)
56562306a36Sopenharmony_ci		goto bg2_fail;
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	for (n = 0; n < 8; n++) {
56862306a36Sopenharmony_ci		ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31,
56962306a36Sopenharmony_ci			     clk_names[AVPLL_B1 + n], n, "avpll_vcoB",
57062306a36Sopenharmony_ci			     BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0);
57162306a36Sopenharmony_ci		if (ret)
57262306a36Sopenharmony_ci			goto bg2_fail;
57362306a36Sopenharmony_ci	}
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	/* reference clock bypass switches */
57662306a36Sopenharmony_ci	parent_names[0] = clk_names[SYSPLL];
57762306a36Sopenharmony_ci	parent_names[1] = clk_names[REFCLK];
57862306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2,
57962306a36Sopenharmony_ci			       0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock);
58062306a36Sopenharmony_ci	if (IS_ERR(hw))
58162306a36Sopenharmony_ci		goto bg2_fail;
58262306a36Sopenharmony_ci	clk_names[SYSPLL] = clk_hw_get_name(hw);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	parent_names[0] = clk_names[MEMPLL];
58562306a36Sopenharmony_ci	parent_names[1] = clk_names[REFCLK];
58662306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2,
58762306a36Sopenharmony_ci			       0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock);
58862306a36Sopenharmony_ci	if (IS_ERR(hw))
58962306a36Sopenharmony_ci		goto bg2_fail;
59062306a36Sopenharmony_ci	clk_names[MEMPLL] = clk_hw_get_name(hw);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	parent_names[0] = clk_names[CPUPLL];
59362306a36Sopenharmony_ci	parent_names[1] = clk_names[REFCLK];
59462306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2,
59562306a36Sopenharmony_ci			       0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock);
59662306a36Sopenharmony_ci	if (IS_ERR(hw))
59762306a36Sopenharmony_ci		goto bg2_fail;
59862306a36Sopenharmony_ci	clk_names[CPUPLL] = clk_hw_get_name(hw);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/* clock muxes */
60162306a36Sopenharmony_ci	parent_names[0] = clk_names[AVPLL_B3];
60262306a36Sopenharmony_ci	parent_names[1] = clk_names[AVPLL_A3];
60362306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2,
60462306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock);
60562306a36Sopenharmony_ci	if (IS_ERR(hw))
60662306a36Sopenharmony_ci		goto bg2_fail;
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	parent_names[0] = clk_names[VIDEO0_PLL];
60962306a36Sopenharmony_ci	parent_names[1] = clk_names[VIDEO_EXT0];
61062306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2,
61162306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock);
61262306a36Sopenharmony_ci	if (IS_ERR(hw))
61362306a36Sopenharmony_ci		goto bg2_fail;
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	parent_names[0] = clk_names[VIDEO1_PLL];
61662306a36Sopenharmony_ci	parent_names[1] = clk_names[VIDEO_EXT0];
61762306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2,
61862306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock);
61962306a36Sopenharmony_ci	if (IS_ERR(hw))
62062306a36Sopenharmony_ci		goto bg2_fail;
62162306a36Sopenharmony_ci
62262306a36Sopenharmony_ci	parent_names[0] = clk_names[AVPLL_A2];
62362306a36Sopenharmony_ci	parent_names[1] = clk_names[AVPLL_B2];
62462306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2,
62562306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock);
62662306a36Sopenharmony_ci	if (IS_ERR(hw))
62762306a36Sopenharmony_ci		goto bg2_fail;
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	parent_names[0] = clk_names[VIDEO2_PLL];
63062306a36Sopenharmony_ci	parent_names[1] = clk_names[VIDEO_EXT0];
63162306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2,
63262306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock);
63362306a36Sopenharmony_ci	if (IS_ERR(hw))
63462306a36Sopenharmony_ci		goto bg2_fail;
63562306a36Sopenharmony_ci
63662306a36Sopenharmony_ci	parent_names[0] = clk_names[AVPLL_B1];
63762306a36Sopenharmony_ci	parent_names[1] = clk_names[AVPLL_A5];
63862306a36Sopenharmony_ci	hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2,
63962306a36Sopenharmony_ci			       0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock);
64062306a36Sopenharmony_ci	if (IS_ERR(hw))
64162306a36Sopenharmony_ci		goto bg2_fail;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	/* clock divider cells */
64462306a36Sopenharmony_ci	for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) {
64562306a36Sopenharmony_ci		const struct berlin2_div_data *dd = &bg2_divs[n];
64662306a36Sopenharmony_ci		int k;
64762306a36Sopenharmony_ci
64862306a36Sopenharmony_ci		for (k = 0; k < dd->num_parents; k++)
64962306a36Sopenharmony_ci			parent_names[k] = clk_names[dd->parent_ids[k]];
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci		hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
65262306a36Sopenharmony_ci				dd->name, dd->div_flags, parent_names,
65362306a36Sopenharmony_ci				dd->num_parents, dd->flags, &lock);
65462306a36Sopenharmony_ci	}
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	/* clock gate cells */
65762306a36Sopenharmony_ci	for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) {
65862306a36Sopenharmony_ci		const struct berlin2_gate_data *gd = &bg2_gates[n];
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci		hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name,
66162306a36Sopenharmony_ci			    gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
66262306a36Sopenharmony_ci			    gd->bit_idx, 0, &lock);
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	/* twdclk is derived from cpu/3 */
66662306a36Sopenharmony_ci	hws[CLKID_TWD] =
66762306a36Sopenharmony_ci		clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	/* check for errors on leaf clocks */
67062306a36Sopenharmony_ci	for (n = 0; n < MAX_CLKS; n++) {
67162306a36Sopenharmony_ci		if (!IS_ERR(hws[n]))
67262306a36Sopenharmony_ci			continue;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci		pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
67562306a36Sopenharmony_ci		goto bg2_fail;
67662306a36Sopenharmony_ci	}
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	/* register clk-provider */
67962306a36Sopenharmony_ci	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	return;
68262306a36Sopenharmony_ci
68362306a36Sopenharmony_cibg2_fail:
68462306a36Sopenharmony_ci	iounmap(gbase);
68562306a36Sopenharmony_ci}
68662306a36Sopenharmony_ciCLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk",
68762306a36Sopenharmony_ci	       berlin2_clock_setup);
688