xref: /openbmc/linux/arch/arm/mach-omap2/cm_common.c (revision 883f464c)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
221325b25SPaul Walmsley /*
321325b25SPaul Walmsley  * OMAP2+ common Clock Management (CM) IP block functions
421325b25SPaul Walmsley  *
521325b25SPaul Walmsley  * Copyright (C) 2012 Texas Instruments, Inc.
6d9a16f9aSPaul Walmsley  * Paul Walmsley
721325b25SPaul Walmsley  *
821325b25SPaul Walmsley  * XXX This code should eventually be moved to a CM driver.
921325b25SPaul Walmsley  */
1021325b25SPaul Walmsley 
1121325b25SPaul Walmsley #include <linux/kernel.h>
1221325b25SPaul Walmsley #include <linux/init.h>
13cc4b1e24SPeter Ujfalusi #include <linux/errno.h>
144794208cSTero Kristo #include <linux/bug.h>
15fe87414fSTero Kristo #include <linux/of.h>
16fe87414fSTero Kristo #include <linux/of_address.h>
1721325b25SPaul Walmsley 
1821325b25SPaul Walmsley #include "cm2xxx.h"
1921325b25SPaul Walmsley #include "cm3xxx.h"
20425dc8b2STero Kristo #include "cm33xx.h"
2121325b25SPaul Walmsley #include "cm44xx.h"
22fe87414fSTero Kristo #include "clock.h"
2321325b25SPaul Walmsley 
2421325b25SPaul Walmsley /*
2521325b25SPaul Walmsley  * cm_ll_data: function pointers to SoC-specific implementations of
2621325b25SPaul Walmsley  * common CM functions
2721325b25SPaul Walmsley  */
2821325b25SPaul Walmsley static struct cm_ll_data null_cm_ll_data;
29a529f8deSBhumika Goyal static const struct cm_ll_data *cm_ll_data = &null_cm_ll_data;
3021325b25SPaul Walmsley 
31d9a16f9aSPaul Walmsley /* cm_base: base virtual address of the CM IP block */
3290129336STero Kristo struct omap_domain_base cm_base;
33d9a16f9aSPaul Walmsley 
34d9a16f9aSPaul Walmsley /* cm2_base: base virtual address of the CM2 IP block (OMAP44xx only) */
3590129336STero Kristo struct omap_domain_base cm2_base;
36d9a16f9aSPaul Walmsley 
375970ca2dSTero Kristo #define CM_NO_CLOCKS		0x1
38425dc8b2STero Kristo #define CM_SINGLE_INSTANCE	0x2
395970ca2dSTero Kristo 
40d9a16f9aSPaul Walmsley /**
41c4ceedcbSPaul Walmsley  * cm_split_idlest_reg - split CM_IDLEST reg addr into its components
42c4ceedcbSPaul Walmsley  * @idlest_reg: CM_IDLEST* virtual address
43c4ceedcbSPaul Walmsley  * @prcm_inst: pointer to an s16 to return the PRCM instance offset
44c4ceedcbSPaul Walmsley  * @idlest_reg_id: pointer to a u8 to return the CM_IDLESTx register ID
45c4ceedcbSPaul Walmsley  *
46c4ceedcbSPaul Walmsley  * Given an absolute CM_IDLEST register address @idlest_reg, passes
47c4ceedcbSPaul Walmsley  * the PRCM instance offset and IDLEST register ID back to the caller
48c4ceedcbSPaul Walmsley  * via the @prcm_inst and @idlest_reg_id.  Returns -EINVAL upon error,
49c4ceedcbSPaul Walmsley  * or 0 upon success.  XXX This function is only needed until absolute
50c4ceedcbSPaul Walmsley  * register addresses are removed from the OMAP struct clk records.
51c4ceedcbSPaul Walmsley  */
cm_split_idlest_reg(struct clk_omap_reg * idlest_reg,s16 * prcm_inst,u8 * idlest_reg_id)526c0afb50STero Kristo int cm_split_idlest_reg(struct clk_omap_reg *idlest_reg, s16 *prcm_inst,
53c4ceedcbSPaul Walmsley 			u8 *idlest_reg_id)
54c4ceedcbSPaul Walmsley {
556301d584STero Kristo 	int ret;
56c4ceedcbSPaul Walmsley 	if (!cm_ll_data->split_idlest_reg) {
57c4ceedcbSPaul Walmsley 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
58c4ceedcbSPaul Walmsley 			  __func__);
59c4ceedcbSPaul Walmsley 		return -EINVAL;
60c4ceedcbSPaul Walmsley 	}
61c4ceedcbSPaul Walmsley 
626301d584STero Kristo 	ret = cm_ll_data->split_idlest_reg(idlest_reg, prcm_inst,
63c4ceedcbSPaul Walmsley 					   idlest_reg_id);
646301d584STero Kristo 	*prcm_inst -= cm_base.offset;
656301d584STero Kristo 	return ret;
66c4ceedcbSPaul Walmsley }
67c4ceedcbSPaul Walmsley 
68c4ceedcbSPaul Walmsley /**
69021b6ff0STero Kristo  * omap_cm_wait_module_ready - wait for a module to leave idle or standby
70021b6ff0STero Kristo  * @part: PRCM partition
71c4ceedcbSPaul Walmsley  * @prcm_mod: PRCM module offset
72021b6ff0STero Kristo  * @idlest_reg: CM_IDLESTx register
73c4ceedcbSPaul Walmsley  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
74c4ceedcbSPaul Walmsley  *
75c4ceedcbSPaul Walmsley  * Wait for the PRCM to indicate that the module identified by
76c4ceedcbSPaul Walmsley  * (@prcm_mod, @idlest_id, @idlest_shift) is clocked.  Return 0 upon
77c4ceedcbSPaul Walmsley  * success, -EBUSY if the module doesn't enable in time, or -EINVAL if
78c4ceedcbSPaul Walmsley  * no per-SoC wait_module_ready() function pointer has been registered
79c4ceedcbSPaul Walmsley  * or if the idlest register is unknown on the SoC.
80c4ceedcbSPaul Walmsley  */
omap_cm_wait_module_ready(u8 part,s16 prcm_mod,u16 idlest_reg,u8 idlest_shift)81021b6ff0STero Kristo int omap_cm_wait_module_ready(u8 part, s16 prcm_mod, u16 idlest_reg,
82021b6ff0STero Kristo 			      u8 idlest_shift)
83c4ceedcbSPaul Walmsley {
84c4ceedcbSPaul Walmsley 	if (!cm_ll_data->wait_module_ready) {
85c4ceedcbSPaul Walmsley 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
86c4ceedcbSPaul Walmsley 			  __func__);
87c4ceedcbSPaul Walmsley 		return -EINVAL;
88c4ceedcbSPaul Walmsley 	}
89c4ceedcbSPaul Walmsley 
90021b6ff0STero Kristo 	return cm_ll_data->wait_module_ready(part, prcm_mod, idlest_reg,
91021b6ff0STero Kristo 					     idlest_shift);
92c4ceedcbSPaul Walmsley }
93c4ceedcbSPaul Walmsley 
94c4ceedcbSPaul Walmsley /**
95a8ae5afaSTero Kristo  * omap_cm_wait_module_idle - wait for a module to enter idle or standby
96a8ae5afaSTero Kristo  * @part: PRCM partition
97a8ae5afaSTero Kristo  * @prcm_mod: PRCM module offset
98a8ae5afaSTero Kristo  * @idlest_reg: CM_IDLESTx register
99a8ae5afaSTero Kristo  * @idlest_shift: shift of the bit in the CM_IDLEST* register to check
100a8ae5afaSTero Kristo  *
101a8ae5afaSTero Kristo  * Wait for the PRCM to indicate that the module identified by
102a8ae5afaSTero Kristo  * (@prcm_mod, @idlest_id, @idlest_shift) is no longer clocked.  Return
103a8ae5afaSTero Kristo  * 0 upon success, -EBUSY if the module doesn't enable in time, or
104a8ae5afaSTero Kristo  * -EINVAL if no per-SoC wait_module_idle() function pointer has been
105a8ae5afaSTero Kristo  * registered or if the idlest register is unknown on the SoC.
106a8ae5afaSTero Kristo  */
omap_cm_wait_module_idle(u8 part,s16 prcm_mod,u16 idlest_reg,u8 idlest_shift)107a8ae5afaSTero Kristo int omap_cm_wait_module_idle(u8 part, s16 prcm_mod, u16 idlest_reg,
108a8ae5afaSTero Kristo 			     u8 idlest_shift)
109a8ae5afaSTero Kristo {
110a8ae5afaSTero Kristo 	if (!cm_ll_data->wait_module_idle) {
111a8ae5afaSTero Kristo 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
112a8ae5afaSTero Kristo 			  __func__);
113a8ae5afaSTero Kristo 		return -EINVAL;
114a8ae5afaSTero Kristo 	}
115a8ae5afaSTero Kristo 
116a8ae5afaSTero Kristo 	return cm_ll_data->wait_module_idle(part, prcm_mod, idlest_reg,
117a8ae5afaSTero Kristo 					    idlest_shift);
118a8ae5afaSTero Kristo }
119a8ae5afaSTero Kristo 
120a8ae5afaSTero Kristo /**
121128603f0STero Kristo  * omap_cm_module_enable - enable a module
122128603f0STero Kristo  * @mode: target mode for the module
123128603f0STero Kristo  * @part: PRCM partition
124128603f0STero Kristo  * @inst: PRCM instance
125128603f0STero Kristo  * @clkctrl_offs: CM_CLKCTRL register offset for the module
126128603f0STero Kristo  *
127128603f0STero Kristo  * Enables clocks for a module identified by (@part, @inst, @clkctrl_offs)
128128603f0STero Kristo  * making its IO space accessible. Return 0 upon success, -EINVAL if no
129128603f0STero Kristo  * per-SoC module_enable() function pointer has been registered.
130128603f0STero Kristo  */
omap_cm_module_enable(u8 mode,u8 part,u16 inst,u16 clkctrl_offs)131128603f0STero Kristo int omap_cm_module_enable(u8 mode, u8 part, u16 inst, u16 clkctrl_offs)
132128603f0STero Kristo {
133128603f0STero Kristo 	if (!cm_ll_data->module_enable) {
134128603f0STero Kristo 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
135128603f0STero Kristo 			  __func__);
136128603f0STero Kristo 		return -EINVAL;
137128603f0STero Kristo 	}
138128603f0STero Kristo 
139128603f0STero Kristo 	cm_ll_data->module_enable(mode, part, inst, clkctrl_offs);
140128603f0STero Kristo 	return 0;
141128603f0STero Kristo }
142128603f0STero Kristo 
143128603f0STero Kristo /**
144128603f0STero Kristo  * omap_cm_module_disable - disable a module
145128603f0STero Kristo  * @part: PRCM partition
146128603f0STero Kristo  * @inst: PRCM instance
147128603f0STero Kristo  * @clkctrl_offs: CM_CLKCTRL register offset for the module
148128603f0STero Kristo  *
149128603f0STero Kristo  * Disables clocks for a module identified by (@part, @inst, @clkctrl_offs)
150128603f0STero Kristo  * makings its IO space inaccessible. Return 0 upon success, -EINVAL if
151128603f0STero Kristo  * no per-SoC module_disable() function pointer has been registered.
152128603f0STero Kristo  */
omap_cm_module_disable(u8 part,u16 inst,u16 clkctrl_offs)153128603f0STero Kristo int omap_cm_module_disable(u8 part, u16 inst, u16 clkctrl_offs)
154128603f0STero Kristo {
155128603f0STero Kristo 	if (!cm_ll_data->module_disable) {
156128603f0STero Kristo 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
157128603f0STero Kristo 			  __func__);
158128603f0STero Kristo 		return -EINVAL;
159128603f0STero Kristo 	}
160128603f0STero Kristo 
161128603f0STero Kristo 	cm_ll_data->module_disable(part, inst, clkctrl_offs);
162128603f0STero Kristo 	return 0;
163128603f0STero Kristo }
164128603f0STero Kristo 
omap_cm_xlate_clkctrl(u8 part,u16 inst,u16 clkctrl_offs)1655fa4a3ccSTero Kristo u32 omap_cm_xlate_clkctrl(u8 part, u16 inst, u16 clkctrl_offs)
1665fa4a3ccSTero Kristo {
1675fa4a3ccSTero Kristo 	if (!cm_ll_data->xlate_clkctrl) {
1685fa4a3ccSTero Kristo 		WARN_ONCE(1, "cm: %s: no low-level function defined\n",
1695fa4a3ccSTero Kristo 			  __func__);
1705fa4a3ccSTero Kristo 		return 0;
1715fa4a3ccSTero Kristo 	}
1725fa4a3ccSTero Kristo 	return cm_ll_data->xlate_clkctrl(part, inst, clkctrl_offs);
1735fa4a3ccSTero Kristo }
1745fa4a3ccSTero Kristo 
175128603f0STero Kristo /**
17621325b25SPaul Walmsley  * cm_register - register per-SoC low-level data with the CM
17721325b25SPaul Walmsley  * @cld: low-level per-SoC OMAP CM data & function pointers to register
17821325b25SPaul Walmsley  *
17921325b25SPaul Walmsley  * Register per-SoC low-level OMAP CM data and function pointers with
18021325b25SPaul Walmsley  * the OMAP CM common interface.  The caller must keep the data
18121325b25SPaul Walmsley  * pointed to by @cld valid until it calls cm_unregister() and
18221325b25SPaul Walmsley  * it returns successfully.  Returns 0 upon success, -EINVAL if @cld
18321325b25SPaul Walmsley  * is NULL, or -EEXIST if cm_register() has already been called
18421325b25SPaul Walmsley  * without an intervening cm_unregister().
18521325b25SPaul Walmsley  */
cm_register(const struct cm_ll_data * cld)186a529f8deSBhumika Goyal int cm_register(const struct cm_ll_data *cld)
18721325b25SPaul Walmsley {
18821325b25SPaul Walmsley 	if (!cld)
18921325b25SPaul Walmsley 		return -EINVAL;
19021325b25SPaul Walmsley 
19121325b25SPaul Walmsley 	if (cm_ll_data != &null_cm_ll_data)
19221325b25SPaul Walmsley 		return -EEXIST;
19321325b25SPaul Walmsley 
19421325b25SPaul Walmsley 	cm_ll_data = cld;
19521325b25SPaul Walmsley 
19621325b25SPaul Walmsley 	return 0;
19721325b25SPaul Walmsley }
19821325b25SPaul Walmsley 
19921325b25SPaul Walmsley /**
20021325b25SPaul Walmsley  * cm_unregister - unregister per-SoC low-level data & function pointers
20121325b25SPaul Walmsley  * @cld: low-level per-SoC OMAP CM data & function pointers to unregister
20221325b25SPaul Walmsley  *
20321325b25SPaul Walmsley  * Unregister per-SoC low-level OMAP CM data and function pointers
20421325b25SPaul Walmsley  * that were previously registered with cm_register().  The
20521325b25SPaul Walmsley  * caller may not destroy any of the data pointed to by @cld until
20621325b25SPaul Walmsley  * this function returns successfully.  Returns 0 upon success, or
20721325b25SPaul Walmsley  * -EINVAL if @cld is NULL or if @cld does not match the struct
20821325b25SPaul Walmsley  * cm_ll_data * previously registered by cm_register().
20921325b25SPaul Walmsley  */
cm_unregister(const struct cm_ll_data * cld)210a529f8deSBhumika Goyal int cm_unregister(const struct cm_ll_data *cld)
21121325b25SPaul Walmsley {
21221325b25SPaul Walmsley 	if (!cld || cm_ll_data != cld)
21321325b25SPaul Walmsley 		return -EINVAL;
21421325b25SPaul Walmsley 
21521325b25SPaul Walmsley 	cm_ll_data = &null_cm_ll_data;
21621325b25SPaul Walmsley 
21721325b25SPaul Walmsley 	return 0;
21821325b25SPaul Walmsley }
219fe87414fSTero Kristo 
220425dc8b2STero Kristo #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
221425dc8b2STero Kristo 	defined(CONFIG_SOC_DRA7XX)
222425dc8b2STero Kristo static struct omap_prcm_init_data cm_data __initdata = {
223fe87414fSTero Kristo 	.index = TI_CLKM_CM,
224425dc8b2STero Kristo 	.init = omap4_cm_init,
225fe87414fSTero Kristo };
226fe87414fSTero Kristo 
227425dc8b2STero Kristo static struct omap_prcm_init_data cm2_data __initdata = {
228fe87414fSTero Kristo 	.index = TI_CLKM_CM2,
229425dc8b2STero Kristo 	.init = omap4_cm_init,
230fe87414fSTero Kristo };
231425dc8b2STero Kristo #endif
232fe87414fSTero Kristo 
233425dc8b2STero Kristo #ifdef CONFIG_ARCH_OMAP2
234425dc8b2STero Kristo static struct omap_prcm_init_data omap2_prcm_data __initdata = {
2355970ca2dSTero Kristo 	.index = TI_CLKM_CM,
236425dc8b2STero Kristo 	.init = omap2xxx_cm_init,
237425dc8b2STero Kristo 	.flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
2385970ca2dSTero Kristo };
239425dc8b2STero Kristo #endif
2405970ca2dSTero Kristo 
241425dc8b2STero Kristo #ifdef CONFIG_ARCH_OMAP3
242425dc8b2STero Kristo static struct omap_prcm_init_data omap3_cm_data __initdata = {
2435970ca2dSTero Kristo 	.index = TI_CLKM_CM,
244425dc8b2STero Kristo 	.init = omap3xxx_cm_init,
245425dc8b2STero Kristo 	.flags = CM_SINGLE_INSTANCE,
2465970ca2dSTero Kristo 
2475970ca2dSTero Kristo 	/*
2485970ca2dSTero Kristo 	 * IVA2 offset is a negative value, must offset the cm_base address
2495970ca2dSTero Kristo 	 * by this to get it to positive side on the iomap
2505970ca2dSTero Kristo 	 */
2515970ca2dSTero Kristo 	.offset = -OMAP3430_IVA2_MOD,
2525970ca2dSTero Kristo };
253425dc8b2STero Kristo #endif
2545970ca2dSTero Kristo 
255425dc8b2STero Kristo #if defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_TI81XX)
256425dc8b2STero Kristo static struct omap_prcm_init_data am3_prcm_data __initdata = {
2575970ca2dSTero Kristo 	.index = TI_CLKM_CM,
258425dc8b2STero Kristo 	.flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
259425dc8b2STero Kristo 	.init = am33xx_cm_init,
2605970ca2dSTero Kristo };
261425dc8b2STero Kristo #endif
2625970ca2dSTero Kristo 
263425dc8b2STero Kristo #ifdef CONFIG_SOC_AM43XX
264425dc8b2STero Kristo static struct omap_prcm_init_data am4_prcm_data __initdata = {
2655970ca2dSTero Kristo 	.index = TI_CLKM_CM,
266425dc8b2STero Kristo 	.flags = CM_NO_CLOCKS | CM_SINGLE_INSTANCE,
267425dc8b2STero Kristo 	.init = omap4_cm_init,
2685970ca2dSTero Kristo };
269425dc8b2STero Kristo #endif
2705970ca2dSTero Kristo 
271425dc8b2STero Kristo static const struct of_device_id omap_cm_dt_match_table[] __initconst = {
272425dc8b2STero Kristo #ifdef CONFIG_ARCH_OMAP2
2735970ca2dSTero Kristo 	{ .compatible = "ti,omap2-prcm", .data = &omap2_prcm_data },
274425dc8b2STero Kristo #endif
275425dc8b2STero Kristo #ifdef CONFIG_ARCH_OMAP3
2765970ca2dSTero Kristo 	{ .compatible = "ti,omap3-cm", .data = &omap3_cm_data },
277425dc8b2STero Kristo #endif
278425dc8b2STero Kristo #ifdef CONFIG_ARCH_OMAP4
279fe87414fSTero Kristo 	{ .compatible = "ti,omap4-cm1", .data = &cm_data },
280fe87414fSTero Kristo 	{ .compatible = "ti,omap4-cm2", .data = &cm2_data },
281425dc8b2STero Kristo #endif
282425dc8b2STero Kristo #ifdef CONFIG_SOC_OMAP5
283fe87414fSTero Kristo 	{ .compatible = "ti,omap5-cm-core-aon", .data = &cm_data },
284fe87414fSTero Kristo 	{ .compatible = "ti,omap5-cm-core", .data = &cm2_data },
285425dc8b2STero Kristo #endif
286425dc8b2STero Kristo #ifdef CONFIG_SOC_DRA7XX
287fe87414fSTero Kristo 	{ .compatible = "ti,dra7-cm-core-aon", .data = &cm_data },
288fe87414fSTero Kristo 	{ .compatible = "ti,dra7-cm-core", .data = &cm2_data },
289425dc8b2STero Kristo #endif
290425dc8b2STero Kristo #ifdef CONFIG_SOC_AM33XX
2915970ca2dSTero Kristo 	{ .compatible = "ti,am3-prcm", .data = &am3_prcm_data },
292425dc8b2STero Kristo #endif
293425dc8b2STero Kristo #ifdef CONFIG_SOC_AM43XX
2945970ca2dSTero Kristo 	{ .compatible = "ti,am4-prcm", .data = &am4_prcm_data },
295425dc8b2STero Kristo #endif
296425dc8b2STero Kristo #ifdef CONFIG_SOC_TI81XX
297425dc8b2STero Kristo 	{ .compatible = "ti,dm814-prcm", .data = &am3_prcm_data },
298425dc8b2STero Kristo 	{ .compatible = "ti,dm816-prcm", .data = &am3_prcm_data },
299425dc8b2STero Kristo #endif
300fe87414fSTero Kristo 	{ }
301fe87414fSTero Kristo };
302fe87414fSTero Kristo 
303fe87414fSTero Kristo /**
3045970ca2dSTero Kristo  * omap2_cm_base_init - initialize iomappings for the CM drivers
3055970ca2dSTero Kristo  *
3065970ca2dSTero Kristo  * Detects and initializes the iomappings for the CM driver, based
3075970ca2dSTero Kristo  * on the DT data. Returns 0 in success, negative error value
3085970ca2dSTero Kristo  * otherwise.
3095970ca2dSTero Kristo  */
omap2_cm_base_init(void)3105970ca2dSTero Kristo int __init omap2_cm_base_init(void)
3115970ca2dSTero Kristo {
3125970ca2dSTero Kristo 	struct device_node *np;
3135970ca2dSTero Kristo 	const struct of_device_id *match;
3145970ca2dSTero Kristo 	struct omap_prcm_init_data *data;
31590129336STero Kristo 	struct resource res;
31690129336STero Kristo 	int ret;
31790129336STero Kristo 	struct omap_domain_base *mem = NULL;
3185970ca2dSTero Kristo 
3195970ca2dSTero Kristo 	for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
3205970ca2dSTero Kristo 		data = (struct omap_prcm_init_data *)match->data;
3215970ca2dSTero Kristo 
32290129336STero Kristo 		ret = of_address_to_resource(np, 0, &res);
323*883f464cSWang Qing 		if (ret) {
324*883f464cSWang Qing 			of_node_put(np);
32590129336STero Kristo 			return ret;
326*883f464cSWang Qing 		}
3275970ca2dSTero Kristo 
3285970ca2dSTero Kristo 		if (data->index == TI_CLKM_CM)
32990129336STero Kristo 			mem = &cm_base;
3305970ca2dSTero Kristo 
3315970ca2dSTero Kristo 		if (data->index == TI_CLKM_CM2)
33290129336STero Kristo 			mem = &cm2_base;
3335970ca2dSTero Kristo 
33490129336STero Kristo 		data->mem = ioremap(res.start, resource_size(&res));
33590129336STero Kristo 
33690129336STero Kristo 		if (mem) {
33790129336STero Kristo 			mem->pa = res.start + data->offset;
33890129336STero Kristo 			mem->va = data->mem + data->offset;
3396301d584STero Kristo 			mem->offset = data->offset;
34090129336STero Kristo 		}
341425dc8b2STero Kristo 
342425dc8b2STero Kristo 		data->np = np;
343425dc8b2STero Kristo 
344425dc8b2STero Kristo 		if (data->init && (data->flags & CM_SINGLE_INSTANCE ||
34590129336STero Kristo 				   (cm_base.va && cm2_base.va)))
346425dc8b2STero Kristo 			data->init(data);
3475970ca2dSTero Kristo 	}
3485970ca2dSTero Kristo 
3495970ca2dSTero Kristo 	return 0;
3505970ca2dSTero Kristo }
3515970ca2dSTero Kristo 
3525970ca2dSTero Kristo /**
353fe87414fSTero Kristo  * omap_cm_init - low level init for the CM drivers
354fe87414fSTero Kristo  *
355fe87414fSTero Kristo  * Initializes the low level clock infrastructure for CM drivers.
356fe87414fSTero Kristo  * Returns 0 in success, negative error value in failure.
357fe87414fSTero Kristo  */
omap_cm_init(void)358fe87414fSTero Kristo int __init omap_cm_init(void)
359fe87414fSTero Kristo {
360fe87414fSTero Kristo 	struct device_node *np;
361fe87414fSTero Kristo 	const struct of_device_id *match;
362fe87414fSTero Kristo 	const struct omap_prcm_init_data *data;
363fe87414fSTero Kristo 	int ret;
364fe87414fSTero Kristo 
365fe87414fSTero Kristo 	for_each_matching_node_and_match(np, omap_cm_dt_match_table, &match) {
366fe87414fSTero Kristo 		data = match->data;
367fe87414fSTero Kristo 
3685970ca2dSTero Kristo 		if (data->flags & CM_NO_CLOCKS)
3695970ca2dSTero Kristo 			continue;
370fe87414fSTero Kristo 
37180cbb224STero Kristo 		ret = omap2_clk_provider_init(np, data->index, NULL, data->mem);
372*883f464cSWang Qing 		if (ret) {
373*883f464cSWang Qing 			of_node_put(np);
374fe87414fSTero Kristo 			return ret;
375fe87414fSTero Kristo 		}
376*883f464cSWang Qing 	}
377fe87414fSTero Kristo 
378fe87414fSTero Kristo 	return 0;
379fe87414fSTero Kristo }
380