18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * MVEBU Core divider clock 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 2013 Marvell 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Ezequiel Garcia <ezequiel.garcia@free-electrons.com> 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/kernel.h> 128c2ecf20Sopenharmony_ci#include <linux/clk-provider.h> 138c2ecf20Sopenharmony_ci#include <linux/io.h> 148c2ecf20Sopenharmony_ci#include <linux/of_address.h> 158c2ecf20Sopenharmony_ci#include <linux/slab.h> 168c2ecf20Sopenharmony_ci#include <linux/delay.h> 178c2ecf20Sopenharmony_ci#include "common.h" 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#define CORE_CLK_DIV_RATIO_MASK 0xff 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * This structure describes the hardware details (bit offset and mask) 238c2ecf20Sopenharmony_ci * to configure one particular core divider clock. Those hardware 248c2ecf20Sopenharmony_ci * details may differ from one SoC to another. This structure is 258c2ecf20Sopenharmony_ci * therefore typically instantiated statically to describe the 268c2ecf20Sopenharmony_ci * hardware details. 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_cistruct clk_corediv_desc { 298c2ecf20Sopenharmony_ci unsigned int mask; 308c2ecf20Sopenharmony_ci unsigned int offset; 318c2ecf20Sopenharmony_ci unsigned int fieldbit; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci/* 358c2ecf20Sopenharmony_ci * This structure describes the hardware details to configure the core 368c2ecf20Sopenharmony_ci * divider clocks on a given SoC. Amongst others, it points to the 378c2ecf20Sopenharmony_ci * array of core divider clock descriptors for this SoC, as well as 388c2ecf20Sopenharmony_ci * the corresponding operations to manipulate them. 398c2ecf20Sopenharmony_ci */ 408c2ecf20Sopenharmony_cistruct clk_corediv_soc_desc { 418c2ecf20Sopenharmony_ci const struct clk_corediv_desc *descs; 428c2ecf20Sopenharmony_ci unsigned int ndescs; 438c2ecf20Sopenharmony_ci const struct clk_ops ops; 448c2ecf20Sopenharmony_ci u32 ratio_reload; 458c2ecf20Sopenharmony_ci u32 enable_bit_offset; 468c2ecf20Sopenharmony_ci u32 ratio_offset; 478c2ecf20Sopenharmony_ci}; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci * This structure represents one core divider clock for the clock 518c2ecf20Sopenharmony_ci * framework, and is dynamically allocated for each core divider clock 528c2ecf20Sopenharmony_ci * existing in the current SoC. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_cistruct clk_corediv { 558c2ecf20Sopenharmony_ci struct clk_hw hw; 568c2ecf20Sopenharmony_ci void __iomem *reg; 578c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc; 588c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc; 598c2ecf20Sopenharmony_ci spinlock_t lock; 608c2ecf20Sopenharmony_ci}; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_cistatic struct clk_onecell_data clk_data; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci/* 658c2ecf20Sopenharmony_ci * Description of the core divider clocks available. For now, we 668c2ecf20Sopenharmony_ci * support only NAND, and it is available at the same register 678c2ecf20Sopenharmony_ci * locations regardless of the SoC. 688c2ecf20Sopenharmony_ci */ 698c2ecf20Sopenharmony_cistatic const struct clk_corediv_desc mvebu_corediv_desc[] = { 708c2ecf20Sopenharmony_ci { .mask = 0x3f, .offset = 8, .fieldbit = 1 }, /* NAND clock */ 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cistatic const struct clk_corediv_desc mv98dx3236_corediv_desc[] = { 748c2ecf20Sopenharmony_ci { .mask = 0x0f, .offset = 6, .fieldbit = 27 }, /* NAND clock */ 758c2ecf20Sopenharmony_ci}; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci#define to_corediv_clk(p) container_of(p, struct clk_corediv, hw) 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistatic int clk_corediv_is_enabled(struct clk_hw *hwclk) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci struct clk_corediv *corediv = to_corediv_clk(hwclk); 828c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 838c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc = corediv->desc; 848c2ecf20Sopenharmony_ci u32 enable_mask = BIT(desc->fieldbit) << soc_desc->enable_bit_offset; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci return !!(readl(corediv->reg) & enable_mask); 878c2ecf20Sopenharmony_ci} 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic int clk_corediv_enable(struct clk_hw *hwclk) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci struct clk_corediv *corediv = to_corediv_clk(hwclk); 928c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 938c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc = corediv->desc; 948c2ecf20Sopenharmony_ci unsigned long flags = 0; 958c2ecf20Sopenharmony_ci u32 reg; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci spin_lock_irqsave(&corediv->lock, flags); 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci reg = readl(corediv->reg); 1008c2ecf20Sopenharmony_ci reg |= (BIT(desc->fieldbit) << soc_desc->enable_bit_offset); 1018c2ecf20Sopenharmony_ci writel(reg, corediv->reg); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&corediv->lock, flags); 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci return 0; 1068c2ecf20Sopenharmony_ci} 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_cistatic void clk_corediv_disable(struct clk_hw *hwclk) 1098c2ecf20Sopenharmony_ci{ 1108c2ecf20Sopenharmony_ci struct clk_corediv *corediv = to_corediv_clk(hwclk); 1118c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 1128c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc = corediv->desc; 1138c2ecf20Sopenharmony_ci unsigned long flags = 0; 1148c2ecf20Sopenharmony_ci u32 reg; 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_ci spin_lock_irqsave(&corediv->lock, flags); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci reg = readl(corediv->reg); 1198c2ecf20Sopenharmony_ci reg &= ~(BIT(desc->fieldbit) << soc_desc->enable_bit_offset); 1208c2ecf20Sopenharmony_ci writel(reg, corediv->reg); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&corediv->lock, flags); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic unsigned long clk_corediv_recalc_rate(struct clk_hw *hwclk, 1268c2ecf20Sopenharmony_ci unsigned long parent_rate) 1278c2ecf20Sopenharmony_ci{ 1288c2ecf20Sopenharmony_ci struct clk_corediv *corediv = to_corediv_clk(hwclk); 1298c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 1308c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc = corediv->desc; 1318c2ecf20Sopenharmony_ci u32 reg, div; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci reg = readl(corediv->reg + soc_desc->ratio_offset); 1348c2ecf20Sopenharmony_ci div = (reg >> desc->offset) & desc->mask; 1358c2ecf20Sopenharmony_ci return parent_rate / div; 1368c2ecf20Sopenharmony_ci} 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_cistatic long clk_corediv_round_rate(struct clk_hw *hwclk, unsigned long rate, 1398c2ecf20Sopenharmony_ci unsigned long *parent_rate) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci /* Valid ratio are 1:4, 1:5, 1:6 and 1:8 */ 1428c2ecf20Sopenharmony_ci u32 div; 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci div = *parent_rate / rate; 1458c2ecf20Sopenharmony_ci if (div < 4) 1468c2ecf20Sopenharmony_ci div = 4; 1478c2ecf20Sopenharmony_ci else if (div > 6) 1488c2ecf20Sopenharmony_ci div = 8; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return *parent_rate / div; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_cistatic int clk_corediv_set_rate(struct clk_hw *hwclk, unsigned long rate, 1548c2ecf20Sopenharmony_ci unsigned long parent_rate) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci struct clk_corediv *corediv = to_corediv_clk(hwclk); 1578c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc = corediv->soc_desc; 1588c2ecf20Sopenharmony_ci const struct clk_corediv_desc *desc = corediv->desc; 1598c2ecf20Sopenharmony_ci unsigned long flags = 0; 1608c2ecf20Sopenharmony_ci u32 reg, div; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci div = parent_rate / rate; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci spin_lock_irqsave(&corediv->lock, flags); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci /* Write new divider to the divider ratio register */ 1678c2ecf20Sopenharmony_ci reg = readl(corediv->reg + soc_desc->ratio_offset); 1688c2ecf20Sopenharmony_ci reg &= ~(desc->mask << desc->offset); 1698c2ecf20Sopenharmony_ci reg |= (div & desc->mask) << desc->offset; 1708c2ecf20Sopenharmony_ci writel(reg, corediv->reg + soc_desc->ratio_offset); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_ci /* Set reload-force for this clock */ 1738c2ecf20Sopenharmony_ci reg = readl(corediv->reg) | BIT(desc->fieldbit); 1748c2ecf20Sopenharmony_ci writel(reg, corediv->reg); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* Now trigger the clock update */ 1778c2ecf20Sopenharmony_ci reg = readl(corediv->reg) | soc_desc->ratio_reload; 1788c2ecf20Sopenharmony_ci writel(reg, corediv->reg); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci /* 1818c2ecf20Sopenharmony_ci * Wait for clocks to settle down, and then clear all the 1828c2ecf20Sopenharmony_ci * ratios request and the reload request. 1838c2ecf20Sopenharmony_ci */ 1848c2ecf20Sopenharmony_ci udelay(1000); 1858c2ecf20Sopenharmony_ci reg &= ~(CORE_CLK_DIV_RATIO_MASK | soc_desc->ratio_reload); 1868c2ecf20Sopenharmony_ci writel(reg, corediv->reg); 1878c2ecf20Sopenharmony_ci udelay(1000); 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&corediv->lock, flags); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return 0; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_cistatic const struct clk_corediv_soc_desc armada370_corediv_soc = { 1958c2ecf20Sopenharmony_ci .descs = mvebu_corediv_desc, 1968c2ecf20Sopenharmony_ci .ndescs = ARRAY_SIZE(mvebu_corediv_desc), 1978c2ecf20Sopenharmony_ci .ops = { 1988c2ecf20Sopenharmony_ci .enable = clk_corediv_enable, 1998c2ecf20Sopenharmony_ci .disable = clk_corediv_disable, 2008c2ecf20Sopenharmony_ci .is_enabled = clk_corediv_is_enabled, 2018c2ecf20Sopenharmony_ci .recalc_rate = clk_corediv_recalc_rate, 2028c2ecf20Sopenharmony_ci .round_rate = clk_corediv_round_rate, 2038c2ecf20Sopenharmony_ci .set_rate = clk_corediv_set_rate, 2048c2ecf20Sopenharmony_ci }, 2058c2ecf20Sopenharmony_ci .ratio_reload = BIT(8), 2068c2ecf20Sopenharmony_ci .enable_bit_offset = 24, 2078c2ecf20Sopenharmony_ci .ratio_offset = 0x8, 2088c2ecf20Sopenharmony_ci}; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_cistatic const struct clk_corediv_soc_desc armada380_corediv_soc = { 2118c2ecf20Sopenharmony_ci .descs = mvebu_corediv_desc, 2128c2ecf20Sopenharmony_ci .ndescs = ARRAY_SIZE(mvebu_corediv_desc), 2138c2ecf20Sopenharmony_ci .ops = { 2148c2ecf20Sopenharmony_ci .enable = clk_corediv_enable, 2158c2ecf20Sopenharmony_ci .disable = clk_corediv_disable, 2168c2ecf20Sopenharmony_ci .is_enabled = clk_corediv_is_enabled, 2178c2ecf20Sopenharmony_ci .recalc_rate = clk_corediv_recalc_rate, 2188c2ecf20Sopenharmony_ci .round_rate = clk_corediv_round_rate, 2198c2ecf20Sopenharmony_ci .set_rate = clk_corediv_set_rate, 2208c2ecf20Sopenharmony_ci }, 2218c2ecf20Sopenharmony_ci .ratio_reload = BIT(8), 2228c2ecf20Sopenharmony_ci .enable_bit_offset = 16, 2238c2ecf20Sopenharmony_ci .ratio_offset = 0x4, 2248c2ecf20Sopenharmony_ci}; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic const struct clk_corediv_soc_desc armada375_corediv_soc = { 2278c2ecf20Sopenharmony_ci .descs = mvebu_corediv_desc, 2288c2ecf20Sopenharmony_ci .ndescs = ARRAY_SIZE(mvebu_corediv_desc), 2298c2ecf20Sopenharmony_ci .ops = { 2308c2ecf20Sopenharmony_ci .recalc_rate = clk_corediv_recalc_rate, 2318c2ecf20Sopenharmony_ci .round_rate = clk_corediv_round_rate, 2328c2ecf20Sopenharmony_ci .set_rate = clk_corediv_set_rate, 2338c2ecf20Sopenharmony_ci }, 2348c2ecf20Sopenharmony_ci .ratio_reload = BIT(8), 2358c2ecf20Sopenharmony_ci .ratio_offset = 0x4, 2368c2ecf20Sopenharmony_ci}; 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_cistatic const struct clk_corediv_soc_desc mv98dx3236_corediv_soc = { 2398c2ecf20Sopenharmony_ci .descs = mv98dx3236_corediv_desc, 2408c2ecf20Sopenharmony_ci .ndescs = ARRAY_SIZE(mv98dx3236_corediv_desc), 2418c2ecf20Sopenharmony_ci .ops = { 2428c2ecf20Sopenharmony_ci .recalc_rate = clk_corediv_recalc_rate, 2438c2ecf20Sopenharmony_ci .round_rate = clk_corediv_round_rate, 2448c2ecf20Sopenharmony_ci .set_rate = clk_corediv_set_rate, 2458c2ecf20Sopenharmony_ci }, 2468c2ecf20Sopenharmony_ci .ratio_reload = BIT(10), 2478c2ecf20Sopenharmony_ci .ratio_offset = 0x8, 2488c2ecf20Sopenharmony_ci}; 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic void __init 2518c2ecf20Sopenharmony_cimvebu_corediv_clk_init(struct device_node *node, 2528c2ecf20Sopenharmony_ci const struct clk_corediv_soc_desc *soc_desc) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci struct clk_init_data init; 2558c2ecf20Sopenharmony_ci struct clk_corediv *corediv; 2568c2ecf20Sopenharmony_ci struct clk **clks; 2578c2ecf20Sopenharmony_ci void __iomem *base; 2588c2ecf20Sopenharmony_ci const char *parent_name; 2598c2ecf20Sopenharmony_ci const char *clk_name; 2608c2ecf20Sopenharmony_ci int i; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci base = of_iomap(node, 0); 2638c2ecf20Sopenharmony_ci if (WARN_ON(!base)) 2648c2ecf20Sopenharmony_ci return; 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci parent_name = of_clk_get_parent_name(node, 0); 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci clk_data.clk_num = soc_desc->ndescs; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci /* clks holds the clock array */ 2718c2ecf20Sopenharmony_ci clks = kcalloc(clk_data.clk_num, sizeof(struct clk *), 2728c2ecf20Sopenharmony_ci GFP_KERNEL); 2738c2ecf20Sopenharmony_ci if (WARN_ON(!clks)) 2748c2ecf20Sopenharmony_ci goto err_unmap; 2758c2ecf20Sopenharmony_ci /* corediv holds the clock specific array */ 2768c2ecf20Sopenharmony_ci corediv = kcalloc(clk_data.clk_num, sizeof(struct clk_corediv), 2778c2ecf20Sopenharmony_ci GFP_KERNEL); 2788c2ecf20Sopenharmony_ci if (WARN_ON(!corediv)) 2798c2ecf20Sopenharmony_ci goto err_free_clks; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci spin_lock_init(&corediv->lock); 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci for (i = 0; i < clk_data.clk_num; i++) { 2848c2ecf20Sopenharmony_ci of_property_read_string_index(node, "clock-output-names", 2858c2ecf20Sopenharmony_ci i, &clk_name); 2868c2ecf20Sopenharmony_ci init.num_parents = 1; 2878c2ecf20Sopenharmony_ci init.parent_names = &parent_name; 2888c2ecf20Sopenharmony_ci init.name = clk_name; 2898c2ecf20Sopenharmony_ci init.ops = &soc_desc->ops; 2908c2ecf20Sopenharmony_ci init.flags = 0; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci corediv[i].soc_desc = soc_desc; 2938c2ecf20Sopenharmony_ci corediv[i].desc = soc_desc->descs + i; 2948c2ecf20Sopenharmony_ci corediv[i].reg = base; 2958c2ecf20Sopenharmony_ci corediv[i].hw.init = &init; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci clks[i] = clk_register(NULL, &corediv[i].hw); 2988c2ecf20Sopenharmony_ci WARN_ON(IS_ERR(clks[i])); 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci clk_data.clks = clks; 3028c2ecf20Sopenharmony_ci of_clk_add_provider(node, of_clk_src_onecell_get, &clk_data); 3038c2ecf20Sopenharmony_ci return; 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_cierr_free_clks: 3068c2ecf20Sopenharmony_ci kfree(clks); 3078c2ecf20Sopenharmony_cierr_unmap: 3088c2ecf20Sopenharmony_ci iounmap(base); 3098c2ecf20Sopenharmony_ci} 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_cistatic void __init armada370_corediv_clk_init(struct device_node *node) 3128c2ecf20Sopenharmony_ci{ 3138c2ecf20Sopenharmony_ci return mvebu_corediv_clk_init(node, &armada370_corediv_soc); 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ciCLK_OF_DECLARE(armada370_corediv_clk, "marvell,armada-370-corediv-clock", 3168c2ecf20Sopenharmony_ci armada370_corediv_clk_init); 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic void __init armada375_corediv_clk_init(struct device_node *node) 3198c2ecf20Sopenharmony_ci{ 3208c2ecf20Sopenharmony_ci return mvebu_corediv_clk_init(node, &armada375_corediv_soc); 3218c2ecf20Sopenharmony_ci} 3228c2ecf20Sopenharmony_ciCLK_OF_DECLARE(armada375_corediv_clk, "marvell,armada-375-corediv-clock", 3238c2ecf20Sopenharmony_ci armada375_corediv_clk_init); 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_cistatic void __init armada380_corediv_clk_init(struct device_node *node) 3268c2ecf20Sopenharmony_ci{ 3278c2ecf20Sopenharmony_ci return mvebu_corediv_clk_init(node, &armada380_corediv_soc); 3288c2ecf20Sopenharmony_ci} 3298c2ecf20Sopenharmony_ciCLK_OF_DECLARE(armada380_corediv_clk, "marvell,armada-380-corediv-clock", 3308c2ecf20Sopenharmony_ci armada380_corediv_clk_init); 3318c2ecf20Sopenharmony_ci 3328c2ecf20Sopenharmony_cistatic void __init mv98dx3236_corediv_clk_init(struct device_node *node) 3338c2ecf20Sopenharmony_ci{ 3348c2ecf20Sopenharmony_ci return mvebu_corediv_clk_init(node, &mv98dx3236_corediv_soc); 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ciCLK_OF_DECLARE(mv98dx3236_corediv_clk, "marvell,mv98dx3236-corediv-clock", 3378c2ecf20Sopenharmony_ci mv98dx3236_corediv_clk_init); 338