162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014 Marvell Technology Group Ltd.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Alexandre Belloni <alexandre.belloni@free-electrons.com>
662306a36Sopenharmony_ci * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.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/berlin2q.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include "berlin2-div.h"
2062306a36Sopenharmony_ci#include "berlin2-pll.h"
2162306a36Sopenharmony_ci#include "common.h"
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#define REG_PINMUX0		0x0018
2462306a36Sopenharmony_ci#define REG_PINMUX5		0x002c
2562306a36Sopenharmony_ci#define REG_SYSPLLCTL0		0x0030
2662306a36Sopenharmony_ci#define REG_SYSPLLCTL4		0x0040
2762306a36Sopenharmony_ci#define REG_CLKENABLE		0x00e8
2862306a36Sopenharmony_ci#define REG_CLKSELECT0		0x00ec
2962306a36Sopenharmony_ci#define REG_CLKSELECT1		0x00f0
3062306a36Sopenharmony_ci#define REG_CLKSELECT2		0x00f4
3162306a36Sopenharmony_ci#define REG_CLKSWITCH0		0x00f8
3262306a36Sopenharmony_ci#define REG_CLKSWITCH1		0x00fc
3362306a36Sopenharmony_ci#define REG_SW_GENERIC0		0x0110
3462306a36Sopenharmony_ci#define REG_SW_GENERIC3		0x011c
3562306a36Sopenharmony_ci#define REG_SDIO0XIN_CLKCTL	0x0158
3662306a36Sopenharmony_ci#define REG_SDIO1XIN_CLKCTL	0x015c
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#define	MAX_CLKS 28
3962306a36Sopenharmony_cistatic struct clk_hw_onecell_data *clk_data;
4062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(lock);
4162306a36Sopenharmony_cistatic void __iomem *gbase;
4262306a36Sopenharmony_cistatic void __iomem *cpupll_base;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_cienum {
4562306a36Sopenharmony_ci	REFCLK,
4662306a36Sopenharmony_ci	SYSPLL, CPUPLL,
4762306a36Sopenharmony_ci	AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
4862306a36Sopenharmony_ci	AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic const char *clk_names[] = {
5262306a36Sopenharmony_ci	[REFCLK]		= "refclk",
5362306a36Sopenharmony_ci	[SYSPLL]		= "syspll",
5462306a36Sopenharmony_ci	[CPUPLL]		= "cpupll",
5562306a36Sopenharmony_ci	[AVPLL_B1]		= "avpll_b1",
5662306a36Sopenharmony_ci	[AVPLL_B2]		= "avpll_b2",
5762306a36Sopenharmony_ci	[AVPLL_B3]		= "avpll_b3",
5862306a36Sopenharmony_ci	[AVPLL_B4]		= "avpll_b4",
5962306a36Sopenharmony_ci	[AVPLL_B5]		= "avpll_b5",
6062306a36Sopenharmony_ci	[AVPLL_B6]		= "avpll_b6",
6162306a36Sopenharmony_ci	[AVPLL_B7]		= "avpll_b7",
6262306a36Sopenharmony_ci	[AVPLL_B8]		= "avpll_b8",
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistatic const struct berlin2_pll_map bg2q_pll_map __initconst = {
6662306a36Sopenharmony_ci	.vcodiv		= {1, 0, 2, 0, 3, 4, 0, 6, 8},
6762306a36Sopenharmony_ci	.mult		= 1,
6862306a36Sopenharmony_ci	.fbdiv_shift	= 7,
6962306a36Sopenharmony_ci	.rfdiv_shift	= 2,
7062306a36Sopenharmony_ci	.divsel_shift	= 9,
7162306a36Sopenharmony_ci};
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_cistatic const u8 default_parent_ids[] = {
7462306a36Sopenharmony_ci	SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cistatic const struct berlin2_div_data bg2q_divs[] __initconst = {
7862306a36Sopenharmony_ci	{
7962306a36Sopenharmony_ci		.name = "sys",
8062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
8162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
8262306a36Sopenharmony_ci		.map = {
8362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
8462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
8562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
8662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
8762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
8862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
8962306a36Sopenharmony_ci		},
9062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
9162306a36Sopenharmony_ci		.flags = CLK_IGNORE_UNUSED,
9262306a36Sopenharmony_ci	},
9362306a36Sopenharmony_ci	{
9462306a36Sopenharmony_ci		.name = "drmfigo",
9562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
9662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
9762306a36Sopenharmony_ci		.map = {
9862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
9962306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
10062306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
10162306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
10262306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
10362306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
10462306a36Sopenharmony_ci		},
10562306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
10662306a36Sopenharmony_ci		.flags = 0,
10762306a36Sopenharmony_ci	},
10862306a36Sopenharmony_ci	{
10962306a36Sopenharmony_ci		.name = "cfg",
11062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
11162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
11262306a36Sopenharmony_ci		.map = {
11362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
11462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
11562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
11662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
11762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
11862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
11962306a36Sopenharmony_ci		},
12062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
12162306a36Sopenharmony_ci		.flags = 0,
12262306a36Sopenharmony_ci	},
12362306a36Sopenharmony_ci	{
12462306a36Sopenharmony_ci		.name = "gfx2d",
12562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
12662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
12762306a36Sopenharmony_ci		.map = {
12862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
12962306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
13062306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
13162306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
13262306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
13362306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
13462306a36Sopenharmony_ci		},
13562306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
13662306a36Sopenharmony_ci		.flags = 0,
13762306a36Sopenharmony_ci	},
13862306a36Sopenharmony_ci	{
13962306a36Sopenharmony_ci		.name = "zsp",
14062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
14162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
14262306a36Sopenharmony_ci		.map = {
14362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
14462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
14562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
14662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
14762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
14862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
14962306a36Sopenharmony_ci		},
15062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
15162306a36Sopenharmony_ci		.flags = 0,
15262306a36Sopenharmony_ci	},
15362306a36Sopenharmony_ci	{
15462306a36Sopenharmony_ci		.name = "perif",
15562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
15662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
15762306a36Sopenharmony_ci		.map = {
15862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
15962306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
16062306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
16162306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
16262306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
16362306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
16462306a36Sopenharmony_ci		},
16562306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
16662306a36Sopenharmony_ci		.flags = CLK_IGNORE_UNUSED,
16762306a36Sopenharmony_ci	},
16862306a36Sopenharmony_ci	{
16962306a36Sopenharmony_ci		.name = "pcube",
17062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
17162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
17262306a36Sopenharmony_ci		.map = {
17362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
17462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
17562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
17662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
17762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
17862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
17962306a36Sopenharmony_ci		},
18062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
18162306a36Sopenharmony_ci		.flags = 0,
18262306a36Sopenharmony_ci	},
18362306a36Sopenharmony_ci	{
18462306a36Sopenharmony_ci		.name = "vscope",
18562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
18662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
18762306a36Sopenharmony_ci		.map = {
18862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
18962306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
19062306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
19162306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
19262306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
19362306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
19462306a36Sopenharmony_ci		},
19562306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
19662306a36Sopenharmony_ci		.flags = 0,
19762306a36Sopenharmony_ci	},
19862306a36Sopenharmony_ci	{
19962306a36Sopenharmony_ci		.name = "nfc_ecc",
20062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
20162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
20262306a36Sopenharmony_ci		.map = {
20362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
20462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
20562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
20662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
20762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
20862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
20962306a36Sopenharmony_ci		},
21062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
21162306a36Sopenharmony_ci		.flags = 0,
21262306a36Sopenharmony_ci	},
21362306a36Sopenharmony_ci	{
21462306a36Sopenharmony_ci		.name = "vpp",
21562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
21662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
21762306a36Sopenharmony_ci		.map = {
21862306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
21962306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
22062306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
22162306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
22262306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
22362306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
22462306a36Sopenharmony_ci		},
22562306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
22662306a36Sopenharmony_ci		.flags = 0,
22762306a36Sopenharmony_ci	},
22862306a36Sopenharmony_ci	{
22962306a36Sopenharmony_ci		.name = "app",
23062306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
23162306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
23262306a36Sopenharmony_ci		.map = {
23362306a36Sopenharmony_ci			BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
23462306a36Sopenharmony_ci			BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
23562306a36Sopenharmony_ci			BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
23662306a36Sopenharmony_ci			BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
23762306a36Sopenharmony_ci			BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
23862306a36Sopenharmony_ci			BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
23962306a36Sopenharmony_ci		},
24062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
24162306a36Sopenharmony_ci		.flags = 0,
24262306a36Sopenharmony_ci	},
24362306a36Sopenharmony_ci	{
24462306a36Sopenharmony_ci		.name = "sdio0xin",
24562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
24662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
24762306a36Sopenharmony_ci		.map = {
24862306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
24962306a36Sopenharmony_ci		},
25062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
25162306a36Sopenharmony_ci		.flags = 0,
25262306a36Sopenharmony_ci	},
25362306a36Sopenharmony_ci	{
25462306a36Sopenharmony_ci		.name = "sdio1xin",
25562306a36Sopenharmony_ci		.parent_ids = default_parent_ids,
25662306a36Sopenharmony_ci		.num_parents = ARRAY_SIZE(default_parent_ids),
25762306a36Sopenharmony_ci		.map = {
25862306a36Sopenharmony_ci			BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
25962306a36Sopenharmony_ci		},
26062306a36Sopenharmony_ci		.div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
26162306a36Sopenharmony_ci		.flags = 0,
26262306a36Sopenharmony_ci	},
26362306a36Sopenharmony_ci};
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_cistatic const struct berlin2_gate_data bg2q_gates[] __initconst = {
26662306a36Sopenharmony_ci	{ "gfx2daxi",	"perif",	5 },
26762306a36Sopenharmony_ci	{ "geth0",	"perif",	8 },
26862306a36Sopenharmony_ci	{ "sata",	"perif",	9 },
26962306a36Sopenharmony_ci	{ "ahbapb",	"perif",	10, CLK_IGNORE_UNUSED },
27062306a36Sopenharmony_ci	{ "usb0",	"perif",	11 },
27162306a36Sopenharmony_ci	{ "usb1",	"perif",	12 },
27262306a36Sopenharmony_ci	{ "usb2",	"perif",	13 },
27362306a36Sopenharmony_ci	{ "usb3",	"perif",	14 },
27462306a36Sopenharmony_ci	{ "pbridge",	"perif",	15, CLK_IGNORE_UNUSED },
27562306a36Sopenharmony_ci	{ "sdio",	"perif",	16 },
27662306a36Sopenharmony_ci	{ "nfc",	"perif",	18 },
27762306a36Sopenharmony_ci	{ "pcie",	"perif",	22 },
27862306a36Sopenharmony_ci};
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_cistatic void __init berlin2q_clock_setup(struct device_node *np)
28162306a36Sopenharmony_ci{
28262306a36Sopenharmony_ci	struct device_node *parent_np = of_get_parent(np);
28362306a36Sopenharmony_ci	const char *parent_names[9];
28462306a36Sopenharmony_ci	struct clk *clk;
28562306a36Sopenharmony_ci	struct clk_hw **hws;
28662306a36Sopenharmony_ci	int n, ret;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
28962306a36Sopenharmony_ci	if (!clk_data) {
29062306a36Sopenharmony_ci		of_node_put(parent_np);
29162306a36Sopenharmony_ci		return;
29262306a36Sopenharmony_ci	}
29362306a36Sopenharmony_ci	clk_data->num = MAX_CLKS;
29462306a36Sopenharmony_ci	hws = clk_data->hws;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	gbase = of_iomap(parent_np, 0);
29762306a36Sopenharmony_ci	if (!gbase) {
29862306a36Sopenharmony_ci		of_node_put(parent_np);
29962306a36Sopenharmony_ci		pr_err("%pOF: Unable to map global base\n", np);
30062306a36Sopenharmony_ci		return;
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/* BG2Q CPU PLL is not part of global registers */
30462306a36Sopenharmony_ci	cpupll_base = of_iomap(parent_np, 1);
30562306a36Sopenharmony_ci	of_node_put(parent_np);
30662306a36Sopenharmony_ci	if (!cpupll_base) {
30762306a36Sopenharmony_ci		pr_err("%pOF: Unable to map cpupll base\n", np);
30862306a36Sopenharmony_ci		iounmap(gbase);
30962306a36Sopenharmony_ci		return;
31062306a36Sopenharmony_ci	}
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	/* overwrite default clock names with DT provided ones */
31362306a36Sopenharmony_ci	clk = of_clk_get_by_name(np, clk_names[REFCLK]);
31462306a36Sopenharmony_ci	if (!IS_ERR(clk)) {
31562306a36Sopenharmony_ci		clk_names[REFCLK] = __clk_get_name(clk);
31662306a36Sopenharmony_ci		clk_put(clk);
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* simple register PLLs */
32062306a36Sopenharmony_ci	ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
32162306a36Sopenharmony_ci				   clk_names[SYSPLL], clk_names[REFCLK], 0);
32262306a36Sopenharmony_ci	if (ret)
32362306a36Sopenharmony_ci		goto bg2q_fail;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
32662306a36Sopenharmony_ci				   clk_names[CPUPLL], clk_names[REFCLK], 0);
32762306a36Sopenharmony_ci	if (ret)
32862306a36Sopenharmony_ci		goto bg2q_fail;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	/* TODO: add BG2Q AVPLL */
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	/*
33362306a36Sopenharmony_ci	 * TODO: add reference clock bypass switches:
33462306a36Sopenharmony_ci	 * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
33562306a36Sopenharmony_ci	 */
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_ci	/* clock divider cells */
33862306a36Sopenharmony_ci	for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
33962306a36Sopenharmony_ci		const struct berlin2_div_data *dd = &bg2q_divs[n];
34062306a36Sopenharmony_ci		int k;
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci		for (k = 0; k < dd->num_parents; k++)
34362306a36Sopenharmony_ci			parent_names[k] = clk_names[dd->parent_ids[k]];
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci		hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
34662306a36Sopenharmony_ci				dd->name, dd->div_flags, parent_names,
34762306a36Sopenharmony_ci				dd->num_parents, dd->flags, &lock);
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci	/* clock gate cells */
35162306a36Sopenharmony_ci	for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
35262306a36Sopenharmony_ci		const struct berlin2_gate_data *gd = &bg2q_gates[n];
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name,
35562306a36Sopenharmony_ci			    gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
35662306a36Sopenharmony_ci			    gd->bit_idx, 0, &lock);
35762306a36Sopenharmony_ci	}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	/* cpuclk divider is fixed to 1 */
36062306a36Sopenharmony_ci	hws[CLKID_CPU] =
36162306a36Sopenharmony_ci		clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
36262306a36Sopenharmony_ci					  0, 1, 1);
36362306a36Sopenharmony_ci	/* twdclk is derived from cpu/3 */
36462306a36Sopenharmony_ci	hws[CLKID_TWD] =
36562306a36Sopenharmony_ci		clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_ci	/* check for errors on leaf clocks */
36862306a36Sopenharmony_ci	for (n = 0; n < MAX_CLKS; n++) {
36962306a36Sopenharmony_ci		if (!IS_ERR(hws[n]))
37062306a36Sopenharmony_ci			continue;
37162306a36Sopenharmony_ci
37262306a36Sopenharmony_ci		pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
37362306a36Sopenharmony_ci		goto bg2q_fail;
37462306a36Sopenharmony_ci	}
37562306a36Sopenharmony_ci
37662306a36Sopenharmony_ci	/* register clk-provider */
37762306a36Sopenharmony_ci	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	return;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_cibg2q_fail:
38262306a36Sopenharmony_ci	iounmap(cpupll_base);
38362306a36Sopenharmony_ci	iounmap(gbase);
38462306a36Sopenharmony_ci}
38562306a36Sopenharmony_ciCLK_OF_DECLARE(berlin2q_clk, "marvell,berlin2q-clk",
38662306a36Sopenharmony_ci	       berlin2q_clock_setup);
387