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