13504395fSJisheng Zhang // SPDX-License-Identifier: GPL-2.0
218882ac5SAlexandre Belloni /*
318882ac5SAlexandre Belloni * Copyright (c) 2014 Marvell Technology Group Ltd.
418882ac5SAlexandre Belloni *
518882ac5SAlexandre Belloni * Alexandre Belloni <alexandre.belloni@free-electrons.com>
618882ac5SAlexandre Belloni * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>
718882ac5SAlexandre Belloni */
818882ac5SAlexandre Belloni
918882ac5SAlexandre Belloni #include <linux/clk.h>
1018882ac5SAlexandre Belloni #include <linux/clk-provider.h>
1162e59c4eSStephen Boyd #include <linux/io.h>
1218882ac5SAlexandre Belloni #include <linux/kernel.h>
1318882ac5SAlexandre Belloni #include <linux/of.h>
1418882ac5SAlexandre Belloni #include <linux/of_address.h>
1518882ac5SAlexandre Belloni #include <linux/slab.h>
1618882ac5SAlexandre Belloni
1718882ac5SAlexandre Belloni #include <dt-bindings/clock/berlin2q.h>
1818882ac5SAlexandre Belloni
1918882ac5SAlexandre Belloni #include "berlin2-div.h"
2018882ac5SAlexandre Belloni #include "berlin2-pll.h"
2118882ac5SAlexandre Belloni #include "common.h"
2218882ac5SAlexandre Belloni
2318882ac5SAlexandre Belloni #define REG_PINMUX0 0x0018
2418882ac5SAlexandre Belloni #define REG_PINMUX5 0x002c
2518882ac5SAlexandre Belloni #define REG_SYSPLLCTL0 0x0030
2618882ac5SAlexandre Belloni #define REG_SYSPLLCTL4 0x0040
2718882ac5SAlexandre Belloni #define REG_CLKENABLE 0x00e8
2818882ac5SAlexandre Belloni #define REG_CLKSELECT0 0x00ec
2918882ac5SAlexandre Belloni #define REG_CLKSELECT1 0x00f0
3018882ac5SAlexandre Belloni #define REG_CLKSELECT2 0x00f4
3118882ac5SAlexandre Belloni #define REG_CLKSWITCH0 0x00f8
3218882ac5SAlexandre Belloni #define REG_CLKSWITCH1 0x00fc
3318882ac5SAlexandre Belloni #define REG_SW_GENERIC0 0x0110
3418882ac5SAlexandre Belloni #define REG_SW_GENERIC3 0x011c
3518882ac5SAlexandre Belloni #define REG_SDIO0XIN_CLKCTL 0x0158
3618882ac5SAlexandre Belloni #define REG_SDIO1XIN_CLKCTL 0x015c
3718882ac5SAlexandre Belloni
38515f1a20SAntoine Tenart #define MAX_CLKS 28
39f6475e29SStephen Boyd static struct clk_hw_onecell_data *clk_data;
4018882ac5SAlexandre Belloni static DEFINE_SPINLOCK(lock);
4118882ac5SAlexandre Belloni static void __iomem *gbase;
4218882ac5SAlexandre Belloni static void __iomem *cpupll_base;
4318882ac5SAlexandre Belloni
4418882ac5SAlexandre Belloni enum {
4518882ac5SAlexandre Belloni REFCLK,
4618882ac5SAlexandre Belloni SYSPLL, CPUPLL,
4718882ac5SAlexandre Belloni AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4,
4818882ac5SAlexandre Belloni AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8,
4918882ac5SAlexandre Belloni };
5018882ac5SAlexandre Belloni
5118882ac5SAlexandre Belloni static const char *clk_names[] = {
5218882ac5SAlexandre Belloni [REFCLK] = "refclk",
5318882ac5SAlexandre Belloni [SYSPLL] = "syspll",
5418882ac5SAlexandre Belloni [CPUPLL] = "cpupll",
5518882ac5SAlexandre Belloni [AVPLL_B1] = "avpll_b1",
5618882ac5SAlexandre Belloni [AVPLL_B2] = "avpll_b2",
5718882ac5SAlexandre Belloni [AVPLL_B3] = "avpll_b3",
5818882ac5SAlexandre Belloni [AVPLL_B4] = "avpll_b4",
5918882ac5SAlexandre Belloni [AVPLL_B5] = "avpll_b5",
6018882ac5SAlexandre Belloni [AVPLL_B6] = "avpll_b6",
6118882ac5SAlexandre Belloni [AVPLL_B7] = "avpll_b7",
6218882ac5SAlexandre Belloni [AVPLL_B8] = "avpll_b8",
6318882ac5SAlexandre Belloni };
6418882ac5SAlexandre Belloni
6518882ac5SAlexandre Belloni static const struct berlin2_pll_map bg2q_pll_map __initconst = {
6618882ac5SAlexandre Belloni .vcodiv = {1, 0, 2, 0, 3, 4, 0, 6, 8},
6718882ac5SAlexandre Belloni .mult = 1,
6818882ac5SAlexandre Belloni .fbdiv_shift = 7,
6918882ac5SAlexandre Belloni .rfdiv_shift = 2,
7018882ac5SAlexandre Belloni .divsel_shift = 9,
7118882ac5SAlexandre Belloni };
7218882ac5SAlexandre Belloni
7318882ac5SAlexandre Belloni static const u8 default_parent_ids[] = {
7418882ac5SAlexandre Belloni SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL
7518882ac5SAlexandre Belloni };
7618882ac5SAlexandre Belloni
7718882ac5SAlexandre Belloni static const struct berlin2_div_data bg2q_divs[] __initconst = {
7818882ac5SAlexandre Belloni {
7918882ac5SAlexandre Belloni .name = "sys",
8018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
8118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
8218882ac5SAlexandre Belloni .map = {
8318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 0),
8418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0),
8518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3),
8618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3),
8718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4),
8818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5),
8918882ac5SAlexandre Belloni },
9018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
9118882ac5SAlexandre Belloni .flags = CLK_IGNORE_UNUSED,
9218882ac5SAlexandre Belloni },
9318882ac5SAlexandre Belloni {
9418882ac5SAlexandre Belloni .name = "drmfigo",
9518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
9618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
9718882ac5SAlexandre Belloni .map = {
9818882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 17),
9918882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6),
10018882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9),
10118882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6),
10218882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7),
10318882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8),
10418882ac5SAlexandre Belloni },
10518882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
10618882ac5SAlexandre Belloni .flags = 0,
10718882ac5SAlexandre Belloni },
10818882ac5SAlexandre Belloni {
10918882ac5SAlexandre Belloni .name = "cfg",
11018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
11118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
11218882ac5SAlexandre Belloni .map = {
11318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 1),
11418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT0, 12),
11518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT0, 15),
11618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 9),
11718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 10),
11818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 11),
11918882ac5SAlexandre Belloni },
12018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
12118882ac5SAlexandre Belloni .flags = 0,
12218882ac5SAlexandre Belloni },
12318882ac5SAlexandre Belloni {
12418882ac5SAlexandre Belloni .name = "gfx2d",
12518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
12618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
12718882ac5SAlexandre Belloni .map = {
12818882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 4),
12918882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT0, 18),
13018882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT0, 21),
13118882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12),
13218882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13),
13318882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14),
13418882ac5SAlexandre Belloni },
13518882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
13618882ac5SAlexandre Belloni .flags = 0,
13718882ac5SAlexandre Belloni },
13818882ac5SAlexandre Belloni {
13918882ac5SAlexandre Belloni .name = "zsp",
14018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
14118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
14218882ac5SAlexandre Belloni .map = {
14318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 6),
14418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT0, 24),
14518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT0, 27),
14618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15),
14718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16),
14818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17),
14918882ac5SAlexandre Belloni },
15018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
15118882ac5SAlexandre Belloni .flags = 0,
15218882ac5SAlexandre Belloni },
15318882ac5SAlexandre Belloni {
15418882ac5SAlexandre Belloni .name = "perif",
15518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
15618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
15718882ac5SAlexandre Belloni .map = {
15818882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 7),
15918882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT1, 0),
16018882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT1, 3),
16118882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18),
16218882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19),
16318882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20),
16418882ac5SAlexandre Belloni },
16518882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
16618882ac5SAlexandre Belloni .flags = CLK_IGNORE_UNUSED,
16718882ac5SAlexandre Belloni },
16818882ac5SAlexandre Belloni {
16918882ac5SAlexandre Belloni .name = "pcube",
17018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
17118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
17218882ac5SAlexandre Belloni .map = {
17318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 2),
17418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT1, 6),
17518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT1, 9),
17618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21),
17718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22),
17818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23),
17918882ac5SAlexandre Belloni },
18018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
18118882ac5SAlexandre Belloni .flags = 0,
18218882ac5SAlexandre Belloni },
18318882ac5SAlexandre Belloni {
18418882ac5SAlexandre Belloni .name = "vscope",
18518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
18618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
18718882ac5SAlexandre Belloni .map = {
18818882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 3),
18918882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT1, 12),
19018882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT1, 15),
19118882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24),
19218882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25),
19318882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26),
19418882ac5SAlexandre Belloni },
19518882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
19618882ac5SAlexandre Belloni .flags = 0,
19718882ac5SAlexandre Belloni },
19818882ac5SAlexandre Belloni {
19918882ac5SAlexandre Belloni .name = "nfc_ecc",
20018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
20118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
20218882ac5SAlexandre Belloni .map = {
20318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 19),
20418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT1, 18),
20518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT1, 21),
20618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27),
20718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28),
20818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29),
20918882ac5SAlexandre Belloni },
21018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
21118882ac5SAlexandre Belloni .flags = 0,
21218882ac5SAlexandre Belloni },
21318882ac5SAlexandre Belloni {
21418882ac5SAlexandre Belloni .name = "vpp",
21518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
21618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
21718882ac5SAlexandre Belloni .map = {
21818882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 21),
21918882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT1, 24),
22018882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT1, 27),
22118882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30),
22218882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31),
22318882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0),
22418882ac5SAlexandre Belloni },
22518882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
22618882ac5SAlexandre Belloni .flags = 0,
22718882ac5SAlexandre Belloni },
22818882ac5SAlexandre Belloni {
22918882ac5SAlexandre Belloni .name = "app",
23018882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
23118882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
23218882ac5SAlexandre Belloni .map = {
23318882ac5SAlexandre Belloni BERLIN2_DIV_GATE(REG_CLKENABLE, 20),
23418882ac5SAlexandre Belloni BERLIN2_PLL_SELECT(REG_CLKSELECT2, 0),
23518882ac5SAlexandre Belloni BERLIN2_DIV_SELECT(REG_CLKSELECT2, 3),
23618882ac5SAlexandre Belloni BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1),
23718882ac5SAlexandre Belloni BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2),
23818882ac5SAlexandre Belloni BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3),
23918882ac5SAlexandre Belloni },
24018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
24118882ac5SAlexandre Belloni .flags = 0,
24218882ac5SAlexandre Belloni },
24318882ac5SAlexandre Belloni {
24418882ac5SAlexandre Belloni .name = "sdio0xin",
24518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
24618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
24718882ac5SAlexandre Belloni .map = {
24818882ac5SAlexandre Belloni BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL),
24918882ac5SAlexandre Belloni },
25018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
25118882ac5SAlexandre Belloni .flags = 0,
25218882ac5SAlexandre Belloni },
25318882ac5SAlexandre Belloni {
25418882ac5SAlexandre Belloni .name = "sdio1xin",
25518882ac5SAlexandre Belloni .parent_ids = default_parent_ids,
25618882ac5SAlexandre Belloni .num_parents = ARRAY_SIZE(default_parent_ids),
25718882ac5SAlexandre Belloni .map = {
25818882ac5SAlexandre Belloni BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL),
25918882ac5SAlexandre Belloni },
26018882ac5SAlexandre Belloni .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX,
26118882ac5SAlexandre Belloni .flags = 0,
26218882ac5SAlexandre Belloni },
26318882ac5SAlexandre Belloni };
26418882ac5SAlexandre Belloni
26518882ac5SAlexandre Belloni static const struct berlin2_gate_data bg2q_gates[] __initconst = {
26618882ac5SAlexandre Belloni { "gfx2daxi", "perif", 5 },
26718882ac5SAlexandre Belloni { "geth0", "perif", 8 },
26818882ac5SAlexandre Belloni { "sata", "perif", 9 },
26918882ac5SAlexandre Belloni { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED },
27018882ac5SAlexandre Belloni { "usb0", "perif", 11 },
27118882ac5SAlexandre Belloni { "usb1", "perif", 12 },
27218882ac5SAlexandre Belloni { "usb2", "perif", 13 },
27318882ac5SAlexandre Belloni { "usb3", "perif", 14 },
27418882ac5SAlexandre Belloni { "pbridge", "perif", 15, CLK_IGNORE_UNUSED },
275123796bbSJisheng Zhang { "sdio", "perif", 16 },
27618882ac5SAlexandre Belloni { "nfc", "perif", 18 },
27718882ac5SAlexandre Belloni { "pcie", "perif", 22 },
27818882ac5SAlexandre Belloni };
27918882ac5SAlexandre Belloni
berlin2q_clock_setup(struct device_node * np)28018882ac5SAlexandre Belloni static void __init berlin2q_clock_setup(struct device_node *np)
28118882ac5SAlexandre Belloni {
28226b3b6b9SAntoine Tenart struct device_node *parent_np = of_get_parent(np);
28318882ac5SAlexandre Belloni const char *parent_names[9];
28418882ac5SAlexandre Belloni struct clk *clk;
285f6475e29SStephen Boyd struct clk_hw **hws;
286f6475e29SStephen Boyd int n, ret;
287f6475e29SStephen Boyd
288acafe7e3SKees Cook clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL);
289*37c381b8SLiang He if (!clk_data) {
290*37c381b8SLiang He of_node_put(parent_np);
291f6475e29SStephen Boyd return;
292*37c381b8SLiang He }
293f6475e29SStephen Boyd clk_data->num = MAX_CLKS;
294f6475e29SStephen Boyd hws = clk_data->hws;
29518882ac5SAlexandre Belloni
296fd26031bSAntoine Tenart gbase = of_iomap(parent_np, 0);
29718882ac5SAlexandre Belloni if (!gbase) {
298*37c381b8SLiang He of_node_put(parent_np);
29916673931SRob Herring pr_err("%pOF: Unable to map global base\n", np);
30018882ac5SAlexandre Belloni return;
30118882ac5SAlexandre Belloni }
30218882ac5SAlexandre Belloni
30318882ac5SAlexandre Belloni /* BG2Q CPU PLL is not part of global registers */
304fd26031bSAntoine Tenart cpupll_base = of_iomap(parent_np, 1);
305*37c381b8SLiang He of_node_put(parent_np);
30618882ac5SAlexandre Belloni if (!cpupll_base) {
30716673931SRob Herring pr_err("%pOF: Unable to map cpupll base\n", np);
30818882ac5SAlexandre Belloni iounmap(gbase);
30918882ac5SAlexandre Belloni return;
31018882ac5SAlexandre Belloni }
31118882ac5SAlexandre Belloni
31218882ac5SAlexandre Belloni /* overwrite default clock names with DT provided ones */
31318882ac5SAlexandre Belloni clk = of_clk_get_by_name(np, clk_names[REFCLK]);
31418882ac5SAlexandre Belloni if (!IS_ERR(clk)) {
31518882ac5SAlexandre Belloni clk_names[REFCLK] = __clk_get_name(clk);
31618882ac5SAlexandre Belloni clk_put(clk);
31718882ac5SAlexandre Belloni }
31818882ac5SAlexandre Belloni
31918882ac5SAlexandre Belloni /* simple register PLLs */
320f6475e29SStephen Boyd ret = berlin2_pll_register(&bg2q_pll_map, gbase + REG_SYSPLLCTL0,
32118882ac5SAlexandre Belloni clk_names[SYSPLL], clk_names[REFCLK], 0);
322f6475e29SStephen Boyd if (ret)
32318882ac5SAlexandre Belloni goto bg2q_fail;
32418882ac5SAlexandre Belloni
325f6475e29SStephen Boyd ret = berlin2_pll_register(&bg2q_pll_map, cpupll_base,
32618882ac5SAlexandre Belloni clk_names[CPUPLL], clk_names[REFCLK], 0);
327f6475e29SStephen Boyd if (ret)
32818882ac5SAlexandre Belloni goto bg2q_fail;
32918882ac5SAlexandre Belloni
33018882ac5SAlexandre Belloni /* TODO: add BG2Q AVPLL */
33118882ac5SAlexandre Belloni
33218882ac5SAlexandre Belloni /*
33318882ac5SAlexandre Belloni * TODO: add reference clock bypass switches:
33418882ac5SAlexandre Belloni * memPLLSWBypass, cpuPLLSWBypass, and sysPLLSWBypass
33518882ac5SAlexandre Belloni */
33618882ac5SAlexandre Belloni
33718882ac5SAlexandre Belloni /* clock divider cells */
33818882ac5SAlexandre Belloni for (n = 0; n < ARRAY_SIZE(bg2q_divs); n++) {
33918882ac5SAlexandre Belloni const struct berlin2_div_data *dd = &bg2q_divs[n];
34018882ac5SAlexandre Belloni int k;
34118882ac5SAlexandre Belloni
34218882ac5SAlexandre Belloni for (k = 0; k < dd->num_parents; k++)
34318882ac5SAlexandre Belloni parent_names[k] = clk_names[dd->parent_ids[k]];
34418882ac5SAlexandre Belloni
345f6475e29SStephen Boyd hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase,
34618882ac5SAlexandre Belloni dd->name, dd->div_flags, parent_names,
34718882ac5SAlexandre Belloni dd->num_parents, dd->flags, &lock);
34818882ac5SAlexandre Belloni }
34918882ac5SAlexandre Belloni
35018882ac5SAlexandre Belloni /* clock gate cells */
35118882ac5SAlexandre Belloni for (n = 0; n < ARRAY_SIZE(bg2q_gates); n++) {
35218882ac5SAlexandre Belloni const struct berlin2_gate_data *gd = &bg2q_gates[n];
35318882ac5SAlexandre Belloni
354f6475e29SStephen Boyd hws[CLKID_GFX2DAXI + n] = clk_hw_register_gate(NULL, gd->name,
35518882ac5SAlexandre Belloni gd->parent_name, gd->flags, gbase + REG_CLKENABLE,
35618882ac5SAlexandre Belloni gd->bit_idx, 0, &lock);
35718882ac5SAlexandre Belloni }
35818882ac5SAlexandre Belloni
359515f1a20SAntoine Tenart /* cpuclk divider is fixed to 1 */
360f6475e29SStephen Boyd hws[CLKID_CPU] =
361f6475e29SStephen Boyd clk_hw_register_fixed_factor(NULL, "cpu", clk_names[CPUPLL],
362515f1a20SAntoine Tenart 0, 1, 1);
363515f1a20SAntoine Tenart /* twdclk is derived from cpu/3 */
364f6475e29SStephen Boyd hws[CLKID_TWD] =
365f6475e29SStephen Boyd clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3);
36618882ac5SAlexandre Belloni
36718882ac5SAlexandre Belloni /* check for errors on leaf clocks */
36818882ac5SAlexandre Belloni for (n = 0; n < MAX_CLKS; n++) {
369f6475e29SStephen Boyd if (!IS_ERR(hws[n]))
37018882ac5SAlexandre Belloni continue;
37118882ac5SAlexandre Belloni
37216673931SRob Herring pr_err("%pOF: Unable to register leaf clock %d\n", np, n);
37318882ac5SAlexandre Belloni goto bg2q_fail;
37418882ac5SAlexandre Belloni }
37518882ac5SAlexandre Belloni
37618882ac5SAlexandre Belloni /* register clk-provider */
3773ca0b51dSStephen Boyd of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
37818882ac5SAlexandre Belloni
37918882ac5SAlexandre Belloni return;
38018882ac5SAlexandre Belloni
38118882ac5SAlexandre Belloni bg2q_fail:
38218882ac5SAlexandre Belloni iounmap(cpupll_base);
38318882ac5SAlexandre Belloni iounmap(gbase);
38418882ac5SAlexandre Belloni }
38526b3b6b9SAntoine Tenart CLK_OF_DECLARE(berlin2q_clk, "marvell,berlin2q-clk",
38626b3b6b9SAntoine Tenart berlin2q_clock_setup);
387