• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/arm/plat-brcm/
1/*
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.
7 */
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>
13
14#include <mach/clkdev.h>
15
16int clk_enable(struct clk *clk)
17{
18	int ret ;
19
20	ret = atomic_inc_return( &clk->ena_cnt );
21	if( ret > 1 )
22		return 0;
23	/* Continue of count was moved from 0 to 1 - reentrant */
24	if( clk->parent )
25		ret = clk_enable( clk->parent );
26	else
27		ret = 0;
28
29	if( ret == 0 )
30		{
31		if( ! clk->ops || ! clk->ops->enable )
32			{
33			if( clk->rate )
34				ret = 0 ;
35			else
36				ret = -EIO;
37			}
38		else
39			{
40			ret =  clk->ops->enable( clk ) ;
41			}
42		}
43
44	if( ret != 0 )
45		atomic_dec( &clk->ena_cnt );
46
47	return ret ;
48}
49EXPORT_SYMBOL(clk_enable);
50
51void clk_disable(struct clk *clk)
52{
53	int ret ;
54
55	ret = atomic_dec_return( &clk->ena_cnt );
56
57	/* Continue if this is the last client to disable - reentrant */
58	if( ret > 0 )
59		return ;
60	BUG_ON( ret < 0 );
61
62	if( ! clk->ops || ! clk->ops->disable )
63		return;
64
65	clk->ops->disable( clk );
66
67	if( clk->parent )
68		clk_disable( clk->parent );
69
70	return ;
71}
72EXPORT_SYMBOL(clk_disable);
73
74unsigned long clk_get_rate(struct clk *clk)
75{
76	/* Recurse to update parent's frequency */
77	if( clk->parent )
78		clk_get_rate( clk->parent );
79	/* Read hardware registers if needed */
80	if( clk->ops && clk->ops->status )
81		clk->ops->status(clk);
82	return clk->rate;
83}
84EXPORT_SYMBOL(clk_get_rate);
85
86long clk_round_rate(struct clk *clk, unsigned long rate)
87{
88	long ret = -EIO;
89	if (clk->ops && clk->ops->round)
90		ret = clk->ops->round(clk, rate);
91	return ret;
92}
93EXPORT_SYMBOL(clk_round_rate);
94
95int clk_set_rate(struct clk *clk, unsigned long rate)
96{
97	int ret = -EIO;
98
99	if( rate == clk->rate )
100		return 0;
101
102	if (clk->ops && clk->ops->setrate)
103		ret = clk->ops->setrate(clk, rate);
104
105	return ret;
106}
107EXPORT_SYMBOL(clk_set_rate);
108
109/*
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.
113 */
114
115int __clk_get(struct clk *clk)
116{
117	int ret ;
118
119	ret = atomic_inc_return( &clk->use_cnt );
120	if( ret > 1 )
121		return 1;
122	if( clk->parent )
123		return __clk_get( clk->parent );
124	return 1;
125}
126
127void __clk_put(struct clk *clk)
128{
129	int ret;
130
131	ret = atomic_dec_return( &clk->use_cnt );
132	if( ret > 0 )
133		return;
134
135	BUG_ON( ret < 0 );
136
137	if( clk->parent )
138		__clk_put( clk->parent );
139}
140