2 * Top-level clock management API
3 * see include/linux/clk.h for description.
4 * These routines are hardware-independent,
5 * and all hardware-specific code is invoked
6 * through the "ops" methods.
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/clk.h>
12 #include <linux/mutex.h>
14 #include <mach/clkdev.h>
16 int clk_enable(struct clk
*clk
)
20 ret
= atomic_inc_return( &clk
->ena_cnt
);
23 /* Continue of count was moved from 0 to 1 - reentrant */
25 ret
= clk_enable( clk
->parent
);
31 if( ! clk
->ops
|| ! clk
->ops
->enable
)
40 ret
= clk
->ops
->enable( clk
) ;
45 atomic_dec( &clk
->ena_cnt
);
49 EXPORT_SYMBOL(clk_enable
);
51 void clk_disable(struct clk
*clk
)
55 ret
= atomic_dec_return( &clk
->ena_cnt
);
57 /* Continue if this is the last client to disable - reentrant */
62 if( ! clk
->ops
|| ! clk
->ops
->disable
)
65 clk
->ops
->disable( clk
);
68 clk_disable( clk
->parent
);
72 EXPORT_SYMBOL(clk_disable
);
74 unsigned long clk_get_rate(struct clk
*clk
)
76 /* Recurse to update parent's frequency */
78 clk_get_rate( clk
->parent
);
79 /* Read hardware registers if needed */
80 if( clk
->ops
&& clk
->ops
->status
)
81 clk
->ops
->status(clk
);
84 EXPORT_SYMBOL(clk_get_rate
);
86 long clk_round_rate(struct clk
*clk
, unsigned long rate
)
89 if (clk
->ops
&& clk
->ops
->round
)
90 ret
= clk
->ops
->round(clk
, rate
);
93 EXPORT_SYMBOL(clk_round_rate
);
95 int clk_set_rate(struct clk
*clk
, unsigned long rate
)
99 if( rate
== clk
->rate
)
102 if (clk
->ops
&& clk
->ops
->setrate
)
103 ret
= clk
->ops
->setrate(clk
, rate
);
107 EXPORT_SYMBOL(clk_set_rate
);
110 * clk_get(), clk_put() are implemented in arch/arm/common/clock.c
111 * but it needs these two stub functions for platform-specific operations.
112 * Reeturn 1 on success 0 on failure.
115 int __clk_get(struct clk
*clk
)
119 ret
= atomic_inc_return( &clk
->use_cnt
);
123 return __clk_get( clk
->parent
);
127 void __clk_put(struct clk
*clk
)
131 ret
= atomic_dec_return( &clk
->use_cnt
);
138 __clk_put( clk
->parent
);