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