18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2014 Marvell Technology Group Ltd. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com> 68c2ecf20Sopenharmony_ci * Alexandre Belloni <alexandre.belloni@free-electrons.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 118c2ecf20Sopenharmony_ci#include <linux/io.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/of.h> 148c2ecf20Sopenharmony_ci#include <linux/of_address.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci#include <dt-bindings/clock/berlin2.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "berlin2-avpll.h" 208c2ecf20Sopenharmony_ci#include "berlin2-div.h" 218c2ecf20Sopenharmony_ci#include "berlin2-pll.h" 228c2ecf20Sopenharmony_ci#include "common.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define REG_PINMUX0 0x0000 258c2ecf20Sopenharmony_ci#define REG_PINMUX1 0x0004 268c2ecf20Sopenharmony_ci#define REG_SYSPLLCTL0 0x0014 278c2ecf20Sopenharmony_ci#define REG_SYSPLLCTL4 0x0024 288c2ecf20Sopenharmony_ci#define REG_MEMPLLCTL0 0x0028 298c2ecf20Sopenharmony_ci#define REG_MEMPLLCTL4 0x0038 308c2ecf20Sopenharmony_ci#define REG_CPUPLLCTL0 0x003c 318c2ecf20Sopenharmony_ci#define REG_CPUPLLCTL4 0x004c 328c2ecf20Sopenharmony_ci#define REG_AVPLLCTL0 0x0050 338c2ecf20Sopenharmony_ci#define REG_AVPLLCTL31 0x00cc 348c2ecf20Sopenharmony_ci#define REG_AVPLLCTL62 0x0148 358c2ecf20Sopenharmony_ci#define REG_PLLSTATUS 0x014c 368c2ecf20Sopenharmony_ci#define REG_CLKENABLE 0x0150 378c2ecf20Sopenharmony_ci#define REG_CLKSELECT0 0x0154 388c2ecf20Sopenharmony_ci#define REG_CLKSELECT1 0x0158 398c2ecf20Sopenharmony_ci#define REG_CLKSELECT2 0x015c 408c2ecf20Sopenharmony_ci#define REG_CLKSELECT3 0x0160 418c2ecf20Sopenharmony_ci#define REG_CLKSWITCH0 0x0164 428c2ecf20Sopenharmony_ci#define REG_CLKSWITCH1 0x0168 438c2ecf20Sopenharmony_ci#define REG_RESET_TRIGGER 0x0178 448c2ecf20Sopenharmony_ci#define REG_RESET_STATUS0 0x017c 458c2ecf20Sopenharmony_ci#define REG_RESET_STATUS1 0x0180 468c2ecf20Sopenharmony_ci#define REG_SW_GENERIC0 0x0184 478c2ecf20Sopenharmony_ci#define REG_SW_GENERIC3 0x0190 488c2ecf20Sopenharmony_ci#define REG_PRODUCTID 0x01cc 498c2ecf20Sopenharmony_ci#define REG_PRODUCTID_EXT 0x01d0 508c2ecf20Sopenharmony_ci#define REG_GFX3DCORE_CLKCTL 0x022c 518c2ecf20Sopenharmony_ci#define REG_GFX3DSYS_CLKCTL 0x0230 528c2ecf20Sopenharmony_ci#define REG_ARC_CLKCTL 0x0234 538c2ecf20Sopenharmony_ci#define REG_VIP_CLKCTL 0x0238 548c2ecf20Sopenharmony_ci#define REG_SDIO0XIN_CLKCTL 0x023c 558c2ecf20Sopenharmony_ci#define REG_SDIO1XIN_CLKCTL 0x0240 568c2ecf20Sopenharmony_ci#define REG_GFX3DEXTRA_CLKCTL 0x0244 578c2ecf20Sopenharmony_ci#define REG_GFX3D_RESET 0x0248 588c2ecf20Sopenharmony_ci#define REG_GC360_CLKCTL 0x024c 598c2ecf20Sopenharmony_ci#define REG_SDIO_DLLMST_CLKCTL 0x0250 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * BG2/BG2CD SoCs have the following audio/video I/O units: 638c2ecf20Sopenharmony_ci * 648c2ecf20Sopenharmony_ci * audiohd: HDMI TX audio 658c2ecf20Sopenharmony_ci * audio0: 7.1ch TX 668c2ecf20Sopenharmony_ci * audio1: 2ch TX 678c2ecf20Sopenharmony_ci * audio2: 2ch RX 688c2ecf20Sopenharmony_ci * audio3: SPDIF TX 698c2ecf20Sopenharmony_ci * video0: HDMI video 708c2ecf20Sopenharmony_ci * video1: Secondary video 718c2ecf20Sopenharmony_ci * video2: SD auxiliary video 728c2ecf20Sopenharmony_ci * 738c2ecf20Sopenharmony_ci * There are no external audio clocks (ACLKI0, ACLKI1) and 748c2ecf20Sopenharmony_ci * only one external video clock (VCLKI0). 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * Currently missing bits and pieces: 778c2ecf20Sopenharmony_ci * - audio_fast_pll is unknown 788c2ecf20Sopenharmony_ci * - audiohd_pll is unknown 798c2ecf20Sopenharmony_ci * - video0_pll is unknown 808c2ecf20Sopenharmony_ci * - audio[023], audiohd parent pll is assumed to be audio_fast_pll 818c2ecf20Sopenharmony_ci * 828c2ecf20Sopenharmony_ci */ 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci#define MAX_CLKS 41 858c2ecf20Sopenharmony_cistatic struct clk_hw_onecell_data *clk_data; 868c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(lock); 878c2ecf20Sopenharmony_cistatic void __iomem *gbase; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cienum { 908c2ecf20Sopenharmony_ci REFCLK, VIDEO_EXT0, 918c2ecf20Sopenharmony_ci SYSPLL, MEMPLL, CPUPLL, 928c2ecf20Sopenharmony_ci AVPLL_A1, AVPLL_A2, AVPLL_A3, AVPLL_A4, 938c2ecf20Sopenharmony_ci AVPLL_A5, AVPLL_A6, AVPLL_A7, AVPLL_A8, 948c2ecf20Sopenharmony_ci AVPLL_B1, AVPLL_B2, AVPLL_B3, AVPLL_B4, 958c2ecf20Sopenharmony_ci AVPLL_B5, AVPLL_B6, AVPLL_B7, AVPLL_B8, 968c2ecf20Sopenharmony_ci AUDIO1_PLL, AUDIO_FAST_PLL, 978c2ecf20Sopenharmony_ci VIDEO0_PLL, VIDEO0_IN, 988c2ecf20Sopenharmony_ci VIDEO1_PLL, VIDEO1_IN, 998c2ecf20Sopenharmony_ci VIDEO2_PLL, VIDEO2_IN, 1008c2ecf20Sopenharmony_ci}; 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic const char *clk_names[] = { 1038c2ecf20Sopenharmony_ci [REFCLK] = "refclk", 1048c2ecf20Sopenharmony_ci [VIDEO_EXT0] = "video_ext0", 1058c2ecf20Sopenharmony_ci [SYSPLL] = "syspll", 1068c2ecf20Sopenharmony_ci [MEMPLL] = "mempll", 1078c2ecf20Sopenharmony_ci [CPUPLL] = "cpupll", 1088c2ecf20Sopenharmony_ci [AVPLL_A1] = "avpll_a1", 1098c2ecf20Sopenharmony_ci [AVPLL_A2] = "avpll_a2", 1108c2ecf20Sopenharmony_ci [AVPLL_A3] = "avpll_a3", 1118c2ecf20Sopenharmony_ci [AVPLL_A4] = "avpll_a4", 1128c2ecf20Sopenharmony_ci [AVPLL_A5] = "avpll_a5", 1138c2ecf20Sopenharmony_ci [AVPLL_A6] = "avpll_a6", 1148c2ecf20Sopenharmony_ci [AVPLL_A7] = "avpll_a7", 1158c2ecf20Sopenharmony_ci [AVPLL_A8] = "avpll_a8", 1168c2ecf20Sopenharmony_ci [AVPLL_B1] = "avpll_b1", 1178c2ecf20Sopenharmony_ci [AVPLL_B2] = "avpll_b2", 1188c2ecf20Sopenharmony_ci [AVPLL_B3] = "avpll_b3", 1198c2ecf20Sopenharmony_ci [AVPLL_B4] = "avpll_b4", 1208c2ecf20Sopenharmony_ci [AVPLL_B5] = "avpll_b5", 1218c2ecf20Sopenharmony_ci [AVPLL_B6] = "avpll_b6", 1228c2ecf20Sopenharmony_ci [AVPLL_B7] = "avpll_b7", 1238c2ecf20Sopenharmony_ci [AVPLL_B8] = "avpll_b8", 1248c2ecf20Sopenharmony_ci [AUDIO1_PLL] = "audio1_pll", 1258c2ecf20Sopenharmony_ci [AUDIO_FAST_PLL] = "audio_fast_pll", 1268c2ecf20Sopenharmony_ci [VIDEO0_PLL] = "video0_pll", 1278c2ecf20Sopenharmony_ci [VIDEO0_IN] = "video0_in", 1288c2ecf20Sopenharmony_ci [VIDEO1_PLL] = "video1_pll", 1298c2ecf20Sopenharmony_ci [VIDEO1_IN] = "video1_in", 1308c2ecf20Sopenharmony_ci [VIDEO2_PLL] = "video2_pll", 1318c2ecf20Sopenharmony_ci [VIDEO2_IN] = "video2_in", 1328c2ecf20Sopenharmony_ci}; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic const struct berlin2_pll_map bg2_pll_map __initconst = { 1358c2ecf20Sopenharmony_ci .vcodiv = {10, 15, 20, 25, 30, 40, 50, 60, 80}, 1368c2ecf20Sopenharmony_ci .mult = 10, 1378c2ecf20Sopenharmony_ci .fbdiv_shift = 6, 1388c2ecf20Sopenharmony_ci .rfdiv_shift = 1, 1398c2ecf20Sopenharmony_ci .divsel_shift = 7, 1408c2ecf20Sopenharmony_ci}; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_cistatic const u8 default_parent_ids[] = { 1438c2ecf20Sopenharmony_ci SYSPLL, AVPLL_B4, AVPLL_A5, AVPLL_B6, AVPLL_B7, SYSPLL 1448c2ecf20Sopenharmony_ci}; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistatic const struct berlin2_div_data bg2_divs[] __initconst = { 1478c2ecf20Sopenharmony_ci { 1488c2ecf20Sopenharmony_ci .name = "sys", 1498c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ 1508c2ecf20Sopenharmony_ci SYSPLL, AVPLL_B4, AVPLL_B5, AVPLL_B6, AVPLL_B7, SYSPLL 1518c2ecf20Sopenharmony_ci }, 1528c2ecf20Sopenharmony_ci .num_parents = 6, 1538c2ecf20Sopenharmony_ci .map = { 1548c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 0), 1558c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT0, 0), 1568c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT0, 3), 1578c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 3), 1588c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 4), 1598c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 5), 1608c2ecf20Sopenharmony_ci }, 1618c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 1628c2ecf20Sopenharmony_ci .flags = CLK_IGNORE_UNUSED, 1638c2ecf20Sopenharmony_ci }, 1648c2ecf20Sopenharmony_ci { 1658c2ecf20Sopenharmony_ci .name = "cpu", 1668c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ 1678c2ecf20Sopenharmony_ci CPUPLL, MEMPLL, MEMPLL, MEMPLL, MEMPLL 1688c2ecf20Sopenharmony_ci }, 1698c2ecf20Sopenharmony_ci .num_parents = 5, 1708c2ecf20Sopenharmony_ci .map = { 1718c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT0, 6), 1728c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT0, 9), 1738c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 6), 1748c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 7), 1758c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 8), 1768c2ecf20Sopenharmony_ci }, 1778c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_MUX, 1788c2ecf20Sopenharmony_ci .flags = 0, 1798c2ecf20Sopenharmony_ci }, 1808c2ecf20Sopenharmony_ci { 1818c2ecf20Sopenharmony_ci .name = "drmfigo", 1828c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 1838c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 1848c2ecf20Sopenharmony_ci .map = { 1858c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 16), 1868c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT0, 17), 1878c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT0, 20), 1888c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 12), 1898c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 13), 1908c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 14), 1918c2ecf20Sopenharmony_ci }, 1928c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 1938c2ecf20Sopenharmony_ci .flags = 0, 1948c2ecf20Sopenharmony_ci }, 1958c2ecf20Sopenharmony_ci { 1968c2ecf20Sopenharmony_ci .name = "cfg", 1978c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 1988c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 1998c2ecf20Sopenharmony_ci .map = { 2008c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 1), 2018c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT0, 23), 2028c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT0, 26), 2038c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 15), 2048c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 16), 2058c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 17), 2068c2ecf20Sopenharmony_ci }, 2078c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2088c2ecf20Sopenharmony_ci .flags = 0, 2098c2ecf20Sopenharmony_ci }, 2108c2ecf20Sopenharmony_ci { 2118c2ecf20Sopenharmony_ci .name = "gfx", 2128c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2138c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2148c2ecf20Sopenharmony_ci .map = { 2158c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 4), 2168c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT0, 29), 2178c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT1, 0), 2188c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 18), 2198c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 19), 2208c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 20), 2218c2ecf20Sopenharmony_ci }, 2228c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2238c2ecf20Sopenharmony_ci .flags = 0, 2248c2ecf20Sopenharmony_ci }, 2258c2ecf20Sopenharmony_ci { 2268c2ecf20Sopenharmony_ci .name = "zsp", 2278c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2288c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2298c2ecf20Sopenharmony_ci .map = { 2308c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 5), 2318c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT1, 3), 2328c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT1, 6), 2338c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 21), 2348c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 22), 2358c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 23), 2368c2ecf20Sopenharmony_ci }, 2378c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2388c2ecf20Sopenharmony_ci .flags = 0, 2398c2ecf20Sopenharmony_ci }, 2408c2ecf20Sopenharmony_ci { 2418c2ecf20Sopenharmony_ci .name = "perif", 2428c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2438c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2448c2ecf20Sopenharmony_ci .map = { 2458c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 6), 2468c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT1, 9), 2478c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT1, 12), 2488c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 24), 2498c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 25), 2508c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 26), 2518c2ecf20Sopenharmony_ci }, 2528c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2538c2ecf20Sopenharmony_ci .flags = CLK_IGNORE_UNUSED, 2548c2ecf20Sopenharmony_ci }, 2558c2ecf20Sopenharmony_ci { 2568c2ecf20Sopenharmony_ci .name = "pcube", 2578c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2588c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2598c2ecf20Sopenharmony_ci .map = { 2608c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 2), 2618c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT1, 15), 2628c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT1, 18), 2638c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 27), 2648c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 28), 2658c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH0, 29), 2668c2ecf20Sopenharmony_ci }, 2678c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2688c2ecf20Sopenharmony_ci .flags = 0, 2698c2ecf20Sopenharmony_ci }, 2708c2ecf20Sopenharmony_ci { 2718c2ecf20Sopenharmony_ci .name = "vscope", 2728c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2738c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2748c2ecf20Sopenharmony_ci .map = { 2758c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 3), 2768c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT1, 21), 2778c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT1, 24), 2788c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH0, 30), 2798c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH0, 31), 2808c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 0), 2818c2ecf20Sopenharmony_ci }, 2828c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2838c2ecf20Sopenharmony_ci .flags = 0, 2848c2ecf20Sopenharmony_ci }, 2858c2ecf20Sopenharmony_ci { 2868c2ecf20Sopenharmony_ci .name = "nfc_ecc", 2878c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 2888c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 2898c2ecf20Sopenharmony_ci .map = { 2908c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 18), 2918c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT1, 27), 2928c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 0), 2938c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 1), 2948c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 2), 2958c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 3), 2968c2ecf20Sopenharmony_ci }, 2978c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 2988c2ecf20Sopenharmony_ci .flags = 0, 2998c2ecf20Sopenharmony_ci }, 3008c2ecf20Sopenharmony_ci { 3018c2ecf20Sopenharmony_ci .name = "vpp", 3028c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 3038c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 3048c2ecf20Sopenharmony_ci .map = { 3058c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 21), 3068c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT2, 3), 3078c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 6), 3088c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 4), 3098c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 5), 3108c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 6), 3118c2ecf20Sopenharmony_ci }, 3128c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 3138c2ecf20Sopenharmony_ci .flags = 0, 3148c2ecf20Sopenharmony_ci }, 3158c2ecf20Sopenharmony_ci { 3168c2ecf20Sopenharmony_ci .name = "app", 3178c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 3188c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 3198c2ecf20Sopenharmony_ci .map = { 3208c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 20), 3218c2ecf20Sopenharmony_ci BERLIN2_PLL_SELECT(REG_CLKSELECT2, 9), 3228c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 12), 3238c2ecf20Sopenharmony_ci BERLIN2_PLL_SWITCH(REG_CLKSWITCH1, 7), 3248c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 8), 3258c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 9), 3268c2ecf20Sopenharmony_ci }, 3278c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 3288c2ecf20Sopenharmony_ci .flags = 0, 3298c2ecf20Sopenharmony_ci }, 3308c2ecf20Sopenharmony_ci { 3318c2ecf20Sopenharmony_ci .name = "audio0", 3328c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ AUDIO_FAST_PLL }, 3338c2ecf20Sopenharmony_ci .num_parents = 1, 3348c2ecf20Sopenharmony_ci .map = { 3358c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 22), 3368c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 17), 3378c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 10), 3388c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 11), 3398c2ecf20Sopenharmony_ci }, 3408c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE, 3418c2ecf20Sopenharmony_ci .flags = 0, 3428c2ecf20Sopenharmony_ci }, 3438c2ecf20Sopenharmony_ci { 3448c2ecf20Sopenharmony_ci .name = "audio2", 3458c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ AUDIO_FAST_PLL }, 3468c2ecf20Sopenharmony_ci .num_parents = 1, 3478c2ecf20Sopenharmony_ci .map = { 3488c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 24), 3498c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 20), 3508c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 14), 3518c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 15), 3528c2ecf20Sopenharmony_ci }, 3538c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE, 3548c2ecf20Sopenharmony_ci .flags = 0, 3558c2ecf20Sopenharmony_ci }, 3568c2ecf20Sopenharmony_ci { 3578c2ecf20Sopenharmony_ci .name = "audio3", 3588c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ AUDIO_FAST_PLL }, 3598c2ecf20Sopenharmony_ci .num_parents = 1, 3608c2ecf20Sopenharmony_ci .map = { 3618c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 25), 3628c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT2, 23), 3638c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 16), 3648c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 17), 3658c2ecf20Sopenharmony_ci }, 3668c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE, 3678c2ecf20Sopenharmony_ci .flags = 0, 3688c2ecf20Sopenharmony_ci }, 3698c2ecf20Sopenharmony_ci { 3708c2ecf20Sopenharmony_ci .name = "audio1", 3718c2ecf20Sopenharmony_ci .parent_ids = (const u8 []){ AUDIO1_PLL }, 3728c2ecf20Sopenharmony_ci .num_parents = 1, 3738c2ecf20Sopenharmony_ci .map = { 3748c2ecf20Sopenharmony_ci BERLIN2_DIV_GATE(REG_CLKENABLE, 23), 3758c2ecf20Sopenharmony_ci BERLIN2_DIV_SELECT(REG_CLKSELECT3, 0), 3768c2ecf20Sopenharmony_ci BERLIN2_DIV_SWITCH(REG_CLKSWITCH1, 12), 3778c2ecf20Sopenharmony_ci BERLIN2_DIV_D3SWITCH(REG_CLKSWITCH1, 13), 3788c2ecf20Sopenharmony_ci }, 3798c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE, 3808c2ecf20Sopenharmony_ci .flags = 0, 3818c2ecf20Sopenharmony_ci }, 3828c2ecf20Sopenharmony_ci { 3838c2ecf20Sopenharmony_ci .name = "gfx3d_core", 3848c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 3858c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 3868c2ecf20Sopenharmony_ci .map = { 3878c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_GFX3DCORE_CLKCTL), 3888c2ecf20Sopenharmony_ci }, 3898c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 3908c2ecf20Sopenharmony_ci .flags = 0, 3918c2ecf20Sopenharmony_ci }, 3928c2ecf20Sopenharmony_ci { 3938c2ecf20Sopenharmony_ci .name = "gfx3d_sys", 3948c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 3958c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 3968c2ecf20Sopenharmony_ci .map = { 3978c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_GFX3DSYS_CLKCTL), 3988c2ecf20Sopenharmony_ci }, 3998c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4008c2ecf20Sopenharmony_ci .flags = 0, 4018c2ecf20Sopenharmony_ci }, 4028c2ecf20Sopenharmony_ci { 4038c2ecf20Sopenharmony_ci .name = "arc", 4048c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4058c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4068c2ecf20Sopenharmony_ci .map = { 4078c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_ARC_CLKCTL), 4088c2ecf20Sopenharmony_ci }, 4098c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4108c2ecf20Sopenharmony_ci .flags = 0, 4118c2ecf20Sopenharmony_ci }, 4128c2ecf20Sopenharmony_ci { 4138c2ecf20Sopenharmony_ci .name = "vip", 4148c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4158c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4168c2ecf20Sopenharmony_ci .map = { 4178c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_VIP_CLKCTL), 4188c2ecf20Sopenharmony_ci }, 4198c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4208c2ecf20Sopenharmony_ci .flags = 0, 4218c2ecf20Sopenharmony_ci }, 4228c2ecf20Sopenharmony_ci { 4238c2ecf20Sopenharmony_ci .name = "sdio0xin", 4248c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4258c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4268c2ecf20Sopenharmony_ci .map = { 4278c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_SDIO0XIN_CLKCTL), 4288c2ecf20Sopenharmony_ci }, 4298c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4308c2ecf20Sopenharmony_ci .flags = 0, 4318c2ecf20Sopenharmony_ci }, 4328c2ecf20Sopenharmony_ci { 4338c2ecf20Sopenharmony_ci .name = "sdio1xin", 4348c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4358c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4368c2ecf20Sopenharmony_ci .map = { 4378c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_SDIO1XIN_CLKCTL), 4388c2ecf20Sopenharmony_ci }, 4398c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4408c2ecf20Sopenharmony_ci .flags = 0, 4418c2ecf20Sopenharmony_ci }, 4428c2ecf20Sopenharmony_ci { 4438c2ecf20Sopenharmony_ci .name = "gfx3d_extra", 4448c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4458c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4468c2ecf20Sopenharmony_ci .map = { 4478c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_GFX3DEXTRA_CLKCTL), 4488c2ecf20Sopenharmony_ci }, 4498c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4508c2ecf20Sopenharmony_ci .flags = 0, 4518c2ecf20Sopenharmony_ci }, 4528c2ecf20Sopenharmony_ci { 4538c2ecf20Sopenharmony_ci .name = "gc360", 4548c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4558c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4568c2ecf20Sopenharmony_ci .map = { 4578c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_GC360_CLKCTL), 4588c2ecf20Sopenharmony_ci }, 4598c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4608c2ecf20Sopenharmony_ci .flags = 0, 4618c2ecf20Sopenharmony_ci }, 4628c2ecf20Sopenharmony_ci { 4638c2ecf20Sopenharmony_ci .name = "sdio_dllmst", 4648c2ecf20Sopenharmony_ci .parent_ids = default_parent_ids, 4658c2ecf20Sopenharmony_ci .num_parents = ARRAY_SIZE(default_parent_ids), 4668c2ecf20Sopenharmony_ci .map = { 4678c2ecf20Sopenharmony_ci BERLIN2_SINGLE_DIV(REG_SDIO_DLLMST_CLKCTL), 4688c2ecf20Sopenharmony_ci }, 4698c2ecf20Sopenharmony_ci .div_flags = BERLIN2_DIV_HAS_GATE | BERLIN2_DIV_HAS_MUX, 4708c2ecf20Sopenharmony_ci .flags = 0, 4718c2ecf20Sopenharmony_ci }, 4728c2ecf20Sopenharmony_ci}; 4738c2ecf20Sopenharmony_ci 4748c2ecf20Sopenharmony_cistatic const struct berlin2_gate_data bg2_gates[] __initconst = { 4758c2ecf20Sopenharmony_ci { "geth0", "perif", 7 }, 4768c2ecf20Sopenharmony_ci { "geth1", "perif", 8 }, 4778c2ecf20Sopenharmony_ci { "sata", "perif", 9 }, 4788c2ecf20Sopenharmony_ci { "ahbapb", "perif", 10, CLK_IGNORE_UNUSED }, 4798c2ecf20Sopenharmony_ci { "usb0", "perif", 11 }, 4808c2ecf20Sopenharmony_ci { "usb1", "perif", 12 }, 4818c2ecf20Sopenharmony_ci { "pbridge", "perif", 13, CLK_IGNORE_UNUSED }, 4828c2ecf20Sopenharmony_ci { "sdio0", "perif", 14 }, 4838c2ecf20Sopenharmony_ci { "sdio1", "perif", 15 }, 4848c2ecf20Sopenharmony_ci { "nfc", "perif", 17 }, 4858c2ecf20Sopenharmony_ci { "smemc", "perif", 19 }, 4868c2ecf20Sopenharmony_ci { "audiohd", "audiohd_pll", 26 }, 4878c2ecf20Sopenharmony_ci { "video0", "video0_in", 27 }, 4888c2ecf20Sopenharmony_ci { "video1", "video1_in", 28 }, 4898c2ecf20Sopenharmony_ci { "video2", "video2_in", 29 }, 4908c2ecf20Sopenharmony_ci}; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_cistatic void __init berlin2_clock_setup(struct device_node *np) 4938c2ecf20Sopenharmony_ci{ 4948c2ecf20Sopenharmony_ci struct device_node *parent_np = of_get_parent(np); 4958c2ecf20Sopenharmony_ci const char *parent_names[9]; 4968c2ecf20Sopenharmony_ci struct clk *clk; 4978c2ecf20Sopenharmony_ci struct clk_hw *hw; 4988c2ecf20Sopenharmony_ci struct clk_hw **hws; 4998c2ecf20Sopenharmony_ci u8 avpll_flags = 0; 5008c2ecf20Sopenharmony_ci int n, ret; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci clk_data = kzalloc(struct_size(clk_data, hws, MAX_CLKS), GFP_KERNEL); 5038c2ecf20Sopenharmony_ci if (!clk_data) { 5048c2ecf20Sopenharmony_ci of_node_put(parent_np); 5058c2ecf20Sopenharmony_ci return; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci clk_data->num = MAX_CLKS; 5088c2ecf20Sopenharmony_ci hws = clk_data->hws; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci gbase = of_iomap(parent_np, 0); 5118c2ecf20Sopenharmony_ci of_node_put(parent_np); 5128c2ecf20Sopenharmony_ci if (!gbase) 5138c2ecf20Sopenharmony_ci return; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* overwrite default clock names with DT provided ones */ 5168c2ecf20Sopenharmony_ci clk = of_clk_get_by_name(np, clk_names[REFCLK]); 5178c2ecf20Sopenharmony_ci if (!IS_ERR(clk)) { 5188c2ecf20Sopenharmony_ci clk_names[REFCLK] = __clk_get_name(clk); 5198c2ecf20Sopenharmony_ci clk_put(clk); 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci 5228c2ecf20Sopenharmony_ci clk = of_clk_get_by_name(np, clk_names[VIDEO_EXT0]); 5238c2ecf20Sopenharmony_ci if (!IS_ERR(clk)) { 5248c2ecf20Sopenharmony_ci clk_names[VIDEO_EXT0] = __clk_get_name(clk); 5258c2ecf20Sopenharmony_ci clk_put(clk); 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci /* simple register PLLs */ 5298c2ecf20Sopenharmony_ci ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_SYSPLLCTL0, 5308c2ecf20Sopenharmony_ci clk_names[SYSPLL], clk_names[REFCLK], 0); 5318c2ecf20Sopenharmony_ci if (ret) 5328c2ecf20Sopenharmony_ci goto bg2_fail; 5338c2ecf20Sopenharmony_ci 5348c2ecf20Sopenharmony_ci ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_MEMPLLCTL0, 5358c2ecf20Sopenharmony_ci clk_names[MEMPLL], clk_names[REFCLK], 0); 5368c2ecf20Sopenharmony_ci if (ret) 5378c2ecf20Sopenharmony_ci goto bg2_fail; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci ret = berlin2_pll_register(&bg2_pll_map, gbase + REG_CPUPLLCTL0, 5408c2ecf20Sopenharmony_ci clk_names[CPUPLL], clk_names[REFCLK], 0); 5418c2ecf20Sopenharmony_ci if (ret) 5428c2ecf20Sopenharmony_ci goto bg2_fail; 5438c2ecf20Sopenharmony_ci 5448c2ecf20Sopenharmony_ci if (of_device_is_compatible(np, "marvell,berlin2-global-register")) 5458c2ecf20Sopenharmony_ci avpll_flags |= BERLIN2_AVPLL_SCRAMBLE_QUIRK; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci /* audio/video VCOs */ 5488c2ecf20Sopenharmony_ci ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL0, "avpll_vcoA", 5498c2ecf20Sopenharmony_ci clk_names[REFCLK], avpll_flags, 0); 5508c2ecf20Sopenharmony_ci if (ret) 5518c2ecf20Sopenharmony_ci goto bg2_fail; 5528c2ecf20Sopenharmony_ci 5538c2ecf20Sopenharmony_ci for (n = 0; n < 8; n++) { 5548c2ecf20Sopenharmony_ci ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL0, 5558c2ecf20Sopenharmony_ci clk_names[AVPLL_A1 + n], n, "avpll_vcoA", 5568c2ecf20Sopenharmony_ci avpll_flags, 0); 5578c2ecf20Sopenharmony_ci if (ret) 5588c2ecf20Sopenharmony_ci goto bg2_fail; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci ret = berlin2_avpll_vco_register(gbase + REG_AVPLLCTL31, "avpll_vcoB", 5628c2ecf20Sopenharmony_ci clk_names[REFCLK], BERLIN2_AVPLL_BIT_QUIRK | 5638c2ecf20Sopenharmony_ci avpll_flags, 0); 5648c2ecf20Sopenharmony_ci if (ret) 5658c2ecf20Sopenharmony_ci goto bg2_fail; 5668c2ecf20Sopenharmony_ci 5678c2ecf20Sopenharmony_ci for (n = 0; n < 8; n++) { 5688c2ecf20Sopenharmony_ci ret = berlin2_avpll_channel_register(gbase + REG_AVPLLCTL31, 5698c2ecf20Sopenharmony_ci clk_names[AVPLL_B1 + n], n, "avpll_vcoB", 5708c2ecf20Sopenharmony_ci BERLIN2_AVPLL_BIT_QUIRK | avpll_flags, 0); 5718c2ecf20Sopenharmony_ci if (ret) 5728c2ecf20Sopenharmony_ci goto bg2_fail; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci /* reference clock bypass switches */ 5768c2ecf20Sopenharmony_ci parent_names[0] = clk_names[SYSPLL]; 5778c2ecf20Sopenharmony_ci parent_names[1] = clk_names[REFCLK]; 5788c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, "syspll_byp", parent_names, 2, 5798c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSWITCH0, 0, 1, 0, &lock); 5808c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 5818c2ecf20Sopenharmony_ci goto bg2_fail; 5828c2ecf20Sopenharmony_ci clk_names[SYSPLL] = clk_hw_get_name(hw); 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci parent_names[0] = clk_names[MEMPLL]; 5858c2ecf20Sopenharmony_ci parent_names[1] = clk_names[REFCLK]; 5868c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, "mempll_byp", parent_names, 2, 5878c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSWITCH0, 1, 1, 0, &lock); 5888c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 5898c2ecf20Sopenharmony_ci goto bg2_fail; 5908c2ecf20Sopenharmony_ci clk_names[MEMPLL] = clk_hw_get_name(hw); 5918c2ecf20Sopenharmony_ci 5928c2ecf20Sopenharmony_ci parent_names[0] = clk_names[CPUPLL]; 5938c2ecf20Sopenharmony_ci parent_names[1] = clk_names[REFCLK]; 5948c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, "cpupll_byp", parent_names, 2, 5958c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSWITCH0, 2, 1, 0, &lock); 5968c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 5978c2ecf20Sopenharmony_ci goto bg2_fail; 5988c2ecf20Sopenharmony_ci clk_names[CPUPLL] = clk_hw_get_name(hw); 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci /* clock muxes */ 6018c2ecf20Sopenharmony_ci parent_names[0] = clk_names[AVPLL_B3]; 6028c2ecf20Sopenharmony_ci parent_names[1] = clk_names[AVPLL_A3]; 6038c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[AUDIO1_PLL], parent_names, 2, 6048c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT2, 29, 1, 0, &lock); 6058c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6068c2ecf20Sopenharmony_ci goto bg2_fail; 6078c2ecf20Sopenharmony_ci 6088c2ecf20Sopenharmony_ci parent_names[0] = clk_names[VIDEO0_PLL]; 6098c2ecf20Sopenharmony_ci parent_names[1] = clk_names[VIDEO_EXT0]; 6108c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[VIDEO0_IN], parent_names, 2, 6118c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT3, 4, 1, 0, &lock); 6128c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6138c2ecf20Sopenharmony_ci goto bg2_fail; 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_ci parent_names[0] = clk_names[VIDEO1_PLL]; 6168c2ecf20Sopenharmony_ci parent_names[1] = clk_names[VIDEO_EXT0]; 6178c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_IN], parent_names, 2, 6188c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT3, 6, 1, 0, &lock); 6198c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6208c2ecf20Sopenharmony_ci goto bg2_fail; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci parent_names[0] = clk_names[AVPLL_A2]; 6238c2ecf20Sopenharmony_ci parent_names[1] = clk_names[AVPLL_B2]; 6248c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[VIDEO1_PLL], parent_names, 2, 6258c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT3, 7, 1, 0, &lock); 6268c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6278c2ecf20Sopenharmony_ci goto bg2_fail; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci parent_names[0] = clk_names[VIDEO2_PLL]; 6308c2ecf20Sopenharmony_ci parent_names[1] = clk_names[VIDEO_EXT0]; 6318c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_IN], parent_names, 2, 6328c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT3, 9, 1, 0, &lock); 6338c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6348c2ecf20Sopenharmony_ci goto bg2_fail; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci parent_names[0] = clk_names[AVPLL_B1]; 6378c2ecf20Sopenharmony_ci parent_names[1] = clk_names[AVPLL_A5]; 6388c2ecf20Sopenharmony_ci hw = clk_hw_register_mux(NULL, clk_names[VIDEO2_PLL], parent_names, 2, 6398c2ecf20Sopenharmony_ci 0, gbase + REG_CLKSELECT3, 10, 1, 0, &lock); 6408c2ecf20Sopenharmony_ci if (IS_ERR(hw)) 6418c2ecf20Sopenharmony_ci goto bg2_fail; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* clock divider cells */ 6448c2ecf20Sopenharmony_ci for (n = 0; n < ARRAY_SIZE(bg2_divs); n++) { 6458c2ecf20Sopenharmony_ci const struct berlin2_div_data *dd = &bg2_divs[n]; 6468c2ecf20Sopenharmony_ci int k; 6478c2ecf20Sopenharmony_ci 6488c2ecf20Sopenharmony_ci for (k = 0; k < dd->num_parents; k++) 6498c2ecf20Sopenharmony_ci parent_names[k] = clk_names[dd->parent_ids[k]]; 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci hws[CLKID_SYS + n] = berlin2_div_register(&dd->map, gbase, 6528c2ecf20Sopenharmony_ci dd->name, dd->div_flags, parent_names, 6538c2ecf20Sopenharmony_ci dd->num_parents, dd->flags, &lock); 6548c2ecf20Sopenharmony_ci } 6558c2ecf20Sopenharmony_ci 6568c2ecf20Sopenharmony_ci /* clock gate cells */ 6578c2ecf20Sopenharmony_ci for (n = 0; n < ARRAY_SIZE(bg2_gates); n++) { 6588c2ecf20Sopenharmony_ci const struct berlin2_gate_data *gd = &bg2_gates[n]; 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci hws[CLKID_GETH0 + n] = clk_hw_register_gate(NULL, gd->name, 6618c2ecf20Sopenharmony_ci gd->parent_name, gd->flags, gbase + REG_CLKENABLE, 6628c2ecf20Sopenharmony_ci gd->bit_idx, 0, &lock); 6638c2ecf20Sopenharmony_ci } 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci /* twdclk is derived from cpu/3 */ 6668c2ecf20Sopenharmony_ci hws[CLKID_TWD] = 6678c2ecf20Sopenharmony_ci clk_hw_register_fixed_factor(NULL, "twd", "cpu", 0, 1, 3); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci /* check for errors on leaf clocks */ 6708c2ecf20Sopenharmony_ci for (n = 0; n < MAX_CLKS; n++) { 6718c2ecf20Sopenharmony_ci if (!IS_ERR(hws[n])) 6728c2ecf20Sopenharmony_ci continue; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci pr_err("%pOF: Unable to register leaf clock %d\n", np, n); 6758c2ecf20Sopenharmony_ci goto bg2_fail; 6768c2ecf20Sopenharmony_ci } 6778c2ecf20Sopenharmony_ci 6788c2ecf20Sopenharmony_ci /* register clk-provider */ 6798c2ecf20Sopenharmony_ci of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data); 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci return; 6828c2ecf20Sopenharmony_ci 6838c2ecf20Sopenharmony_cibg2_fail: 6848c2ecf20Sopenharmony_ci iounmap(gbase); 6858c2ecf20Sopenharmony_ci} 6868c2ecf20Sopenharmony_ciCLK_OF_DECLARE(berlin2_clk, "marvell,berlin2-clk", 6878c2ecf20Sopenharmony_ci berlin2_clock_setup); 688