brintos

brintos / linux-shallow public Read only

0
0
Text · 15.3 KiB · 030186d Raw
520 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Nuvoton NPCM7xx Clock Generator4 * All the clocks are initialized by the bootloader, so this driver allow only5 * reading of current settings directly from the hardware.6 *7 * Copyright (C) 2018 Nuvoton Technologies tali.perry@nuvoton.com8 */9 10#include <linux/module.h>11#include <linux/clk-provider.h>12#include <linux/io.h>13#include <linux/kernel.h>14#include <linux/of.h>15#include <linux/of_address.h>16#include <linux/slab.h>17#include <linux/err.h>18#include <linux/bitfield.h>19 20#include <dt-bindings/clock/nuvoton,npcm7xx-clock.h>21 22struct npcm7xx_clk_pll {23	struct clk_hw	hw;24	void __iomem	*pllcon;25	u8		flags;26};27 28#define to_npcm7xx_clk_pll(_hw) container_of(_hw, struct npcm7xx_clk_pll, hw)29 30#define PLLCON_LOKI	BIT(31)31#define PLLCON_LOKS	BIT(30)32#define PLLCON_FBDV	GENMASK(27, 16)33#define PLLCON_OTDV2	GENMASK(15, 13)34#define PLLCON_PWDEN	BIT(12)35#define PLLCON_OTDV1	GENMASK(10, 8)36#define PLLCON_INDV	GENMASK(5, 0)37 38static unsigned long npcm7xx_clk_pll_recalc_rate(struct clk_hw *hw,39						 unsigned long parent_rate)40{41	struct npcm7xx_clk_pll *pll = to_npcm7xx_clk_pll(hw);42	unsigned long fbdv, indv, otdv1, otdv2;43	unsigned int val;44	u64 ret;45 46	if (parent_rate == 0) {47		pr_err("%s: parent rate is zero", __func__);48		return 0;49	}50 51	val = readl_relaxed(pll->pllcon);52 53	indv = FIELD_GET(PLLCON_INDV, val);54	fbdv = FIELD_GET(PLLCON_FBDV, val);55	otdv1 = FIELD_GET(PLLCON_OTDV1, val);56	otdv2 = FIELD_GET(PLLCON_OTDV2, val);57 58	ret = (u64)parent_rate * fbdv;59	do_div(ret, indv * otdv1 * otdv2);60 61	return ret;62}63 64static const struct clk_ops npcm7xx_clk_pll_ops = {65	.recalc_rate = npcm7xx_clk_pll_recalc_rate,66};67 68static struct clk_hw *69npcm7xx_clk_register_pll(void __iomem *pllcon, const char *name,70			 const char *parent_name, unsigned long flags)71{72	struct npcm7xx_clk_pll *pll;73	struct clk_init_data init;74	struct clk_hw *hw;75	int ret;76 77	pll = kzalloc(sizeof(*pll), GFP_KERNEL);78	if (!pll)79		return ERR_PTR(-ENOMEM);80 81	pr_debug("%s reg, name=%s, p=%s\n", __func__, name, parent_name);82 83	init.name = name;84	init.ops = &npcm7xx_clk_pll_ops;85	init.parent_names = &parent_name;86	init.num_parents = 1;87	init.flags = flags;88 89	pll->pllcon = pllcon;90	pll->hw.init = &init;91 92	hw = &pll->hw;93 94	ret = clk_hw_register(NULL, hw);95	if (ret) {96		kfree(pll);97		hw = ERR_PTR(ret);98	}99 100	return hw;101}102 103#define NPCM7XX_CLKEN1          (0x00)104#define NPCM7XX_CLKEN2          (0x28)105#define NPCM7XX_CLKEN3          (0x30)106#define NPCM7XX_CLKSEL          (0x04)107#define NPCM7XX_CLKDIV1         (0x08)108#define NPCM7XX_CLKDIV2         (0x2C)109#define NPCM7XX_CLKDIV3         (0x58)110#define NPCM7XX_PLLCON0         (0x0C)111#define NPCM7XX_PLLCON1         (0x10)112#define NPCM7XX_PLLCON2         (0x54)113#define NPCM7XX_SWRSTR          (0x14)114#define NPCM7XX_IRQWAKECON      (0x18)115#define NPCM7XX_IRQWAKEFLAG     (0x1C)116#define NPCM7XX_IPSRST1         (0x20)117#define NPCM7XX_IPSRST2         (0x24)118#define NPCM7XX_IPSRST3         (0x34)119#define NPCM7XX_WD0RCR          (0x38)120#define NPCM7XX_WD1RCR          (0x3C)121#define NPCM7XX_WD2RCR          (0x40)122#define NPCM7XX_SWRSTC1         (0x44)123#define NPCM7XX_SWRSTC2         (0x48)124#define NPCM7XX_SWRSTC3         (0x4C)125#define NPCM7XX_SWRSTC4         (0x50)126#define NPCM7XX_CORSTC          (0x5C)127#define NPCM7XX_PLLCONG         (0x60)128#define NPCM7XX_AHBCKFI         (0x64)129#define NPCM7XX_SECCNT          (0x68)130#define NPCM7XX_CNTR25M         (0x6C)131 132struct npcm7xx_clk_mux_data {133	u8 shift;134	u8 mask;135	u32 *table;136	const char *name;137	const char * const *parent_names;138	u8 num_parents;139	unsigned long flags;140	/*141	 * If this clock is exported via DT, set onecell_idx to constant142	 * defined in include/dt-bindings/clock/nuvoton, NPCM7XX-clock.h for143	 * this specific clock.  Otherwise, set to -1.144	 */145	int onecell_idx;146 147};148 149struct npcm7xx_clk_div_data {150	u32 reg;151	u8 shift;152	u8 width;153	const char *name;154	const char *parent_name;155	u8 clk_divider_flags;156	unsigned long flags;157	/*158	 * If this clock is exported via DT, set onecell_idx to constant159	 * defined in include/dt-bindings/clock/nuvoton, NPCM7XX-clock.h for160	 * this specific clock.  Otherwise, set to -1.161	 */162	int onecell_idx;163};164 165struct npcm7xx_clk_pll_data {166	u32 reg;167	const char *name;168	const char *parent_name;169	unsigned long flags;170	/*171	 * If this clock is exported via DT, set onecell_idx to constant172	 * defined in include/dt-bindings/clock/nuvoton, NPCM7XX-clock.h for173	 * this specific clock.  Otherwise, set to -1.174	 */175	int onecell_idx;176};177 178/*179 * Single copy of strings used to refer to clocks within this driver indexed by180 * above enum.181 */182#define NPCM7XX_CLK_S_REFCLK      "refclk"183#define NPCM7XX_CLK_S_SYSBYPCK    "sysbypck"184#define NPCM7XX_CLK_S_MCBYPCK     "mcbypck"185#define NPCM7XX_CLK_S_GFXBYPCK    "gfxbypck"186#define NPCM7XX_CLK_S_PLL0        "pll0"187#define NPCM7XX_CLK_S_PLL1        "pll1"188#define NPCM7XX_CLK_S_PLL1_DIV2   "pll1_div2"189#define NPCM7XX_CLK_S_PLL2        "pll2"190#define NPCM7XX_CLK_S_PLL_GFX     "pll_gfx"191#define NPCM7XX_CLK_S_PLL2_DIV2   "pll2_div2"192#define NPCM7XX_CLK_S_PIX_MUX     "gfx_pixel"193#define NPCM7XX_CLK_S_GPRFSEL_MUX "gprfsel_mux"194#define NPCM7XX_CLK_S_MC_MUX      "mc_phy"195#define NPCM7XX_CLK_S_CPU_MUX     "cpu"  /*AKA system clock.*/196#define NPCM7XX_CLK_S_MC          "mc"197#define NPCM7XX_CLK_S_AXI         "axi"  /*AKA CLK2*/198#define NPCM7XX_CLK_S_AHB         "ahb"  /*AKA CLK4*/199#define NPCM7XX_CLK_S_CLKOUT_MUX  "clkout_mux"200#define NPCM7XX_CLK_S_UART_MUX    "uart_mux"201#define NPCM7XX_CLK_S_TIM_MUX     "timer_mux"202#define NPCM7XX_CLK_S_SD_MUX      "sd_mux"203#define NPCM7XX_CLK_S_GFXM_MUX    "gfxm_mux"204#define NPCM7XX_CLK_S_SU_MUX      "serial_usb_mux"205#define NPCM7XX_CLK_S_DVC_MUX     "dvc_mux"206#define NPCM7XX_CLK_S_GFX_MUX     "gfx_mux"207#define NPCM7XX_CLK_S_GFX_PIXEL   "gfx_pixel"208#define NPCM7XX_CLK_S_SPI0        "spi0"209#define NPCM7XX_CLK_S_SPI3        "spi3"210#define NPCM7XX_CLK_S_SPIX        "spix"211#define NPCM7XX_CLK_S_APB1        "apb1"212#define NPCM7XX_CLK_S_APB2        "apb2"213#define NPCM7XX_CLK_S_APB3        "apb3"214#define NPCM7XX_CLK_S_APB4        "apb4"215#define NPCM7XX_CLK_S_APB5        "apb5"216#define NPCM7XX_CLK_S_TOCK        "tock"217#define NPCM7XX_CLK_S_CLKOUT      "clkout"218#define NPCM7XX_CLK_S_UART        "uart"219#define NPCM7XX_CLK_S_TIMER       "timer"220#define NPCM7XX_CLK_S_MMC         "mmc"221#define NPCM7XX_CLK_S_SDHC        "sdhc"222#define NPCM7XX_CLK_S_ADC         "adc"223#define NPCM7XX_CLK_S_GFX         "gfx0_gfx1_mem"224#define NPCM7XX_CLK_S_USBIF       "serial_usbif"225#define NPCM7XX_CLK_S_USB_HOST    "usb_host"226#define NPCM7XX_CLK_S_USB_BRIDGE  "usb_bridge"227#define NPCM7XX_CLK_S_PCI         "pci"228 229static u32 pll_mux_table[] = {0, 1, 2, 3};230static const char * const pll_mux_parents[] __initconst = {231	NPCM7XX_CLK_S_PLL0,232	NPCM7XX_CLK_S_PLL1_DIV2,233	NPCM7XX_CLK_S_REFCLK,234	NPCM7XX_CLK_S_PLL2_DIV2,235};236 237static u32 cpuck_mux_table[] = {0, 1, 2, 3};238static const char * const cpuck_mux_parents[] __initconst = {239	NPCM7XX_CLK_S_PLL0,240	NPCM7XX_CLK_S_PLL1_DIV2,241	NPCM7XX_CLK_S_REFCLK,242	NPCM7XX_CLK_S_SYSBYPCK,243};244 245static u32 pixcksel_mux_table[] = {0, 2};246static const char * const pixcksel_mux_parents[] __initconst = {247	NPCM7XX_CLK_S_PLL_GFX,248	NPCM7XX_CLK_S_REFCLK,249};250 251static u32 sucksel_mux_table[] = {2, 3};252static const char * const sucksel_mux_parents[] __initconst = {253	NPCM7XX_CLK_S_REFCLK,254	NPCM7XX_CLK_S_PLL2_DIV2,255};256 257static u32 mccksel_mux_table[] = {0, 2, 3};258static const char * const mccksel_mux_parents[] __initconst = {259	NPCM7XX_CLK_S_PLL1_DIV2,260	NPCM7XX_CLK_S_REFCLK,261	NPCM7XX_CLK_S_MCBYPCK,262};263 264static u32 clkoutsel_mux_table[] = {0, 1, 2, 3, 4};265static const char * const clkoutsel_mux_parents[] __initconst = {266	NPCM7XX_CLK_S_PLL0,267	NPCM7XX_CLK_S_PLL1_DIV2,268	NPCM7XX_CLK_S_REFCLK,269	NPCM7XX_CLK_S_PLL_GFX, // divided by 2270	NPCM7XX_CLK_S_PLL2_DIV2,271};272 273static u32 gfxmsel_mux_table[] = {2, 3};274static const char * const gfxmsel_mux_parents[] __initconst = {275	NPCM7XX_CLK_S_REFCLK,276	NPCM7XX_CLK_S_PLL2_DIV2,277};278 279static u32 dvcssel_mux_table[] = {2, 3};280static const char * const dvcssel_mux_parents[] __initconst = {281	NPCM7XX_CLK_S_REFCLK,282	NPCM7XX_CLK_S_PLL2,283};284 285static const struct npcm7xx_clk_pll_data npcm7xx_plls[] __initconst = {286	{NPCM7XX_PLLCON0, NPCM7XX_CLK_S_PLL0, NPCM7XX_CLK_S_REFCLK, 0, -1},287 288	{NPCM7XX_PLLCON1, NPCM7XX_CLK_S_PLL1,289	NPCM7XX_CLK_S_REFCLK, 0, -1},290 291	{NPCM7XX_PLLCON2, NPCM7XX_CLK_S_PLL2,292	NPCM7XX_CLK_S_REFCLK, 0, -1},293 294	{NPCM7XX_PLLCONG, NPCM7XX_CLK_S_PLL_GFX,295	NPCM7XX_CLK_S_REFCLK, 0, -1},296};297 298static const struct npcm7xx_clk_mux_data npcm7xx_muxes[] __initconst = {299	{0, GENMASK(1, 0), cpuck_mux_table, NPCM7XX_CLK_S_CPU_MUX,300	cpuck_mux_parents, ARRAY_SIZE(cpuck_mux_parents), CLK_IS_CRITICAL,301	NPCM7XX_CLK_CPU},302 303	{4, GENMASK(1, 0), pixcksel_mux_table, NPCM7XX_CLK_S_PIX_MUX,304	pixcksel_mux_parents, ARRAY_SIZE(pixcksel_mux_parents), 0,305	NPCM7XX_CLK_GFX_PIXEL},306 307	{6, GENMASK(1, 0), pll_mux_table, NPCM7XX_CLK_S_SD_MUX,308	pll_mux_parents, ARRAY_SIZE(pll_mux_parents), 0, -1},309 310	{8, GENMASK(1, 0), pll_mux_table, NPCM7XX_CLK_S_UART_MUX,311	pll_mux_parents, ARRAY_SIZE(pll_mux_parents), 0, -1},312 313	{10, GENMASK(1, 0), sucksel_mux_table, NPCM7XX_CLK_S_SU_MUX,314	sucksel_mux_parents, ARRAY_SIZE(sucksel_mux_parents), 0, -1},315 316	{12, GENMASK(1, 0), mccksel_mux_table, NPCM7XX_CLK_S_MC_MUX,317	mccksel_mux_parents, ARRAY_SIZE(mccksel_mux_parents), 0, -1},318 319	{14, GENMASK(1, 0), pll_mux_table, NPCM7XX_CLK_S_TIM_MUX,320	pll_mux_parents, ARRAY_SIZE(pll_mux_parents), 0, -1},321 322	{16, GENMASK(1, 0), pll_mux_table, NPCM7XX_CLK_S_GFX_MUX,323	pll_mux_parents, ARRAY_SIZE(pll_mux_parents), 0, -1},324 325	{18, GENMASK(2, 0), clkoutsel_mux_table, NPCM7XX_CLK_S_CLKOUT_MUX,326	clkoutsel_mux_parents, ARRAY_SIZE(clkoutsel_mux_parents), 0, -1},327 328	{21, GENMASK(1, 0), gfxmsel_mux_table, NPCM7XX_CLK_S_GFXM_MUX,329	gfxmsel_mux_parents, ARRAY_SIZE(gfxmsel_mux_parents), 0, -1},330 331	{23, GENMASK(1, 0), dvcssel_mux_table, NPCM7XX_CLK_S_DVC_MUX,332	dvcssel_mux_parents, ARRAY_SIZE(dvcssel_mux_parents), 0, -1},333};334 335/* configurable dividers: */336static const struct npcm7xx_clk_div_data npcm7xx_divs[] __initconst = {337	{NPCM7XX_CLKDIV1, 28, 3, NPCM7XX_CLK_S_ADC,338	NPCM7XX_CLK_S_TIMER, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_ADC},339	/*30-28 ADCCKDIV*/340	{NPCM7XX_CLKDIV1, 26, 2, NPCM7XX_CLK_S_AHB,341	NPCM7XX_CLK_S_AXI, 0, CLK_IS_CRITICAL, NPCM7XX_CLK_AHB},342	/*27-26 CLK4DIV*/343	{NPCM7XX_CLKDIV1, 21, 5, NPCM7XX_CLK_S_TIMER,344	NPCM7XX_CLK_S_TIM_MUX, 0, 0, NPCM7XX_CLK_TIMER},345	/*25-21 TIMCKDIV*/346	{NPCM7XX_CLKDIV1, 16, 5, NPCM7XX_CLK_S_UART,347	NPCM7XX_CLK_S_UART_MUX, 0, 0, NPCM7XX_CLK_UART},348	/*20-16 UARTDIV*/349	{NPCM7XX_CLKDIV1, 11, 5, NPCM7XX_CLK_S_MMC,350	NPCM7XX_CLK_S_SD_MUX, 0, 0, NPCM7XX_CLK_MMC},351	/*15-11 MMCCKDIV*/352	{NPCM7XX_CLKDIV1, 6, 5, NPCM7XX_CLK_S_SPI3,353	NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPI3},354	/*10-6 AHB3CKDIV*/355	{NPCM7XX_CLKDIV1, 2, 4, NPCM7XX_CLK_S_PCI,356	NPCM7XX_CLK_S_GFX_MUX, 0, 0, NPCM7XX_CLK_PCI},357	/*5-2 PCICKDIV*/358	{NPCM7XX_CLKDIV1, 0, 1, NPCM7XX_CLK_S_AXI,359	NPCM7XX_CLK_S_CPU_MUX, CLK_DIVIDER_POWER_OF_TWO, CLK_IS_CRITICAL,360	NPCM7XX_CLK_AXI},/*0 CLK2DIV*/361 362	{NPCM7XX_CLKDIV2, 30, 2, NPCM7XX_CLK_S_APB4,363	NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB4},364	/*31-30 APB4CKDIV*/365	{NPCM7XX_CLKDIV2, 28, 2, NPCM7XX_CLK_S_APB3,366	NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB3},367	/*29-28 APB3CKDIV*/368	{NPCM7XX_CLKDIV2, 26, 2, NPCM7XX_CLK_S_APB2,369	NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB2},370	/*27-26 APB2CKDIV*/371	{NPCM7XX_CLKDIV2, 24, 2, NPCM7XX_CLK_S_APB1,372	NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB1},373	/*25-24 APB1CKDIV*/374	{NPCM7XX_CLKDIV2, 22, 2, NPCM7XX_CLK_S_APB5,375	NPCM7XX_CLK_S_AHB, CLK_DIVIDER_POWER_OF_TWO, 0, NPCM7XX_CLK_APB5},376	/*23-22 APB5CKDIV*/377	{NPCM7XX_CLKDIV2, 16, 5, NPCM7XX_CLK_S_CLKOUT,378	NPCM7XX_CLK_S_CLKOUT_MUX, 0, 0, NPCM7XX_CLK_CLKOUT},379	/*20-16 CLKOUTDIV*/380	{NPCM7XX_CLKDIV2, 13, 3, NPCM7XX_CLK_S_GFX,381	NPCM7XX_CLK_S_GFX_MUX, 0, 0, NPCM7XX_CLK_GFX},382	/*15-13 GFXCKDIV*/383	{NPCM7XX_CLKDIV2, 8, 5, NPCM7XX_CLK_S_USB_BRIDGE,384	NPCM7XX_CLK_S_SU_MUX, 0, 0, NPCM7XX_CLK_SU},385	/*12-8 SUCKDIV*/386	{NPCM7XX_CLKDIV2, 4, 4, NPCM7XX_CLK_S_USB_HOST,387	NPCM7XX_CLK_S_SU_MUX, 0, 0, NPCM7XX_CLK_SU48},388	/*7-4 SU48CKDIV*/389	{NPCM7XX_CLKDIV2, 0, 4, NPCM7XX_CLK_S_SDHC,390	NPCM7XX_CLK_S_SD_MUX, 0, 0, NPCM7XX_CLK_SDHC}391	,/*3-0 SD1CKDIV*/392 393	{NPCM7XX_CLKDIV3, 6, 5, NPCM7XX_CLK_S_SPI0,394	NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPI0},395	/*10-6 SPI0CKDV*/396	{NPCM7XX_CLKDIV3, 1, 5, NPCM7XX_CLK_S_SPIX,397	NPCM7XX_CLK_S_AHB, 0, 0, NPCM7XX_CLK_SPIX},398	/*5-1 SPIXCKDV*/399 400};401 402static DEFINE_SPINLOCK(npcm7xx_clk_lock);403 404static void __init npcm7xx_clk_init(struct device_node *clk_np)405{406	struct clk_hw_onecell_data *npcm7xx_clk_data;407	void __iomem *clk_base;408	struct resource res;409	struct clk_hw *hw;410	int ret;411	int i;412 413	ret = of_address_to_resource(clk_np, 0, &res);414	if (ret) {415		pr_err("%pOFn: failed to get resource, ret %d\n", clk_np,416			ret);417		return;418	}419 420	clk_base = ioremap(res.start, resource_size(&res));421	if (!clk_base)422		goto npcm7xx_init_error;423 424	npcm7xx_clk_data = kzalloc(struct_size(npcm7xx_clk_data, hws,425				   NPCM7XX_NUM_CLOCKS), GFP_KERNEL);426	if (!npcm7xx_clk_data)427		goto npcm7xx_init_np_err;428 429	npcm7xx_clk_data->num = NPCM7XX_NUM_CLOCKS;430 431	for (i = 0; i < NPCM7XX_NUM_CLOCKS; i++)432		npcm7xx_clk_data->hws[i] = ERR_PTR(-EPROBE_DEFER);433 434	/* Register plls */435	for (i = 0; i < ARRAY_SIZE(npcm7xx_plls); i++) {436		const struct npcm7xx_clk_pll_data *pll_data = &npcm7xx_plls[i];437 438		hw = npcm7xx_clk_register_pll(clk_base + pll_data->reg,439			pll_data->name, pll_data->parent_name, pll_data->flags);440		if (IS_ERR(hw)) {441			pr_err("npcm7xx_clk: Can't register pll\n");442			goto npcm7xx_init_fail;443		}444 445		if (pll_data->onecell_idx >= 0)446			npcm7xx_clk_data->hws[pll_data->onecell_idx] = hw;447	}448 449	/* Register fixed dividers */450	hw = clk_hw_register_fixed_factor(NULL, NPCM7XX_CLK_S_PLL1_DIV2,451			NPCM7XX_CLK_S_PLL1, 0, 1, 2);452	if (IS_ERR(hw)) {453		pr_err("npcm7xx_clk: Can't register fixed div\n");454		goto npcm7xx_init_fail;455	}456 457	hw = clk_hw_register_fixed_factor(NULL, NPCM7XX_CLK_S_PLL2_DIV2,458			NPCM7XX_CLK_S_PLL2, 0, 1, 2);459	if (IS_ERR(hw)) {460		pr_err("npcm7xx_clk: Can't register div2\n");461		goto npcm7xx_init_fail;462	}463 464	/* Register muxes */465	for (i = 0; i < ARRAY_SIZE(npcm7xx_muxes); i++) {466		const struct npcm7xx_clk_mux_data *mux_data = &npcm7xx_muxes[i];467 468		hw = clk_hw_register_mux_table(NULL,469			mux_data->name,470			mux_data->parent_names, mux_data->num_parents,471			mux_data->flags, clk_base + NPCM7XX_CLKSEL,472			mux_data->shift, mux_data->mask, 0,473			mux_data->table, &npcm7xx_clk_lock);474 475		if (IS_ERR(hw)) {476			pr_err("npcm7xx_clk: Can't register mux\n");477			goto npcm7xx_init_fail;478		}479 480		if (mux_data->onecell_idx >= 0)481			npcm7xx_clk_data->hws[mux_data->onecell_idx] = hw;482	}483 484	/* Register clock dividers specified in npcm7xx_divs */485	for (i = 0; i < ARRAY_SIZE(npcm7xx_divs); i++) {486		const struct npcm7xx_clk_div_data *div_data = &npcm7xx_divs[i];487 488		hw = clk_hw_register_divider(NULL, div_data->name,489				div_data->parent_name,490				div_data->flags,491				clk_base + div_data->reg,492				div_data->shift, div_data->width,493				div_data->clk_divider_flags, &npcm7xx_clk_lock);494		if (IS_ERR(hw)) {495			pr_err("npcm7xx_clk: Can't register div table\n");496			goto npcm7xx_init_fail;497		}498 499		if (div_data->onecell_idx >= 0)500			npcm7xx_clk_data->hws[div_data->onecell_idx] = hw;501	}502 503	ret = of_clk_add_hw_provider(clk_np, of_clk_hw_onecell_get,504					npcm7xx_clk_data);505	if (ret)506		pr_err("failed to add DT provider: %d\n", ret);507 508	of_node_put(clk_np);509 510	return;511 512npcm7xx_init_fail:513	kfree(npcm7xx_clk_data);514npcm7xx_init_np_err:515	iounmap(clk_base);516npcm7xx_init_error:517	of_node_put(clk_np);518}519CLK_OF_DECLARE(npcm7xx_clk_init, "nuvoton,npcm750-clk", npcm7xx_clk_init);520