2 * arch/arm/mach-ns9xxx/clock.c
4 * Copyright (C) 2007 by Digi International Inc.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
11 #include <linux/err.h>
12 #include <linux/module.h>
13 #include <linux/list.h>
14 #include <linux/clk.h>
15 #include <linux/string.h>
16 #include <linux/platform_device.h>
18 #include <asm/semaphore.h>
21 static LIST_HEAD(clocks
);
22 static DEFINE_SPINLOCK(clk_lock
);
24 struct clk
*clk_get(struct device
*dev
, const char *id
)
26 struct clk
*p
, *ret
= NULL
, *retgen
= NULL
;
30 if (dev
== NULL
|| dev
->bus
!= &platform_bus_type
)
33 idno
= to_platform_device(dev
)->id
;
35 spin_lock_irqsave(&clk_lock
, flags
);
36 list_for_each_entry(p
, &clocks
, node
) {
37 if (strcmp(id
, p
->name
) == 0) {
39 if (!try_module_get(p
->owner
))
43 } else if (p
->id
== -1)
44 /* remember match with id == -1 in case there is
45 * no clock for idno */
50 if (!ret
&& retgen
&& try_module_get(retgen
->owner
))
56 spin_unlock_irqrestore(&clk_lock
, flags
);
58 return ret
? ret
: ERR_PTR(-ENOENT
);
60 EXPORT_SYMBOL(clk_get
);
62 void clk_put(struct clk
*clk
)
64 module_put(clk
->owner
);
67 EXPORT_SYMBOL(clk_put
);
69 static int clk_enable_unlocked(struct clk
*clk
)
73 ret
= clk_enable_unlocked(clk
->parent
);
78 if (clk
->usage
++ == 0 && clk
->endisable
)
79 ret
= clk
->endisable(clk
, 1);
84 int clk_enable(struct clk
*clk
)
89 spin_lock_irqsave(&clk_lock
, flags
);
91 ret
= clk_enable_unlocked(clk
);
93 spin_unlock_irqrestore(&clk_lock
, flags
);
97 EXPORT_SYMBOL(clk_enable
);
99 static void clk_disable_unlocked(struct clk
*clk
)
101 if (--clk
->usage
== 0 && clk
->endisable
)
102 clk
->endisable(clk
, 0);
105 clk_disable_unlocked(clk
->parent
);
108 void clk_disable(struct clk
*clk
)
112 spin_lock_irqsave(&clk_lock
, flags
);
114 clk_disable_unlocked(clk
);
116 spin_unlock_irqrestore(&clk_lock
, flags
);
118 EXPORT_SYMBOL(clk_disable
);
120 unsigned long clk_get_rate(struct clk
*clk
)
123 return clk
->get_rate(clk
);
129 return clk_get_rate(clk
->parent
);
133 EXPORT_SYMBOL(clk_get_rate
);
135 int clk_register(struct clk
*clk
)
139 spin_lock_irqsave(&clk_lock
, flags
);
141 list_add(&clk
->node
, &clocks
);
144 ++clk
->parent
->refcount
;
146 spin_unlock_irqrestore(&clk_lock
, flags
);
151 int clk_unregister(struct clk
*clk
)
156 spin_lock_irqsave(&clk_lock
, flags
);
158 if (clk
->usage
|| clk
->refcount
)
161 list_del(&clk
->node
);
164 --clk
->parent
->refcount
;
166 spin_unlock_irqrestore(&clk_lock
, flags
);
171 #if defined CONFIG_DEBUG_FS
173 #include <linux/debugfs.h>
174 #include <linux/seq_file.h>
176 static int clk_debugfs_show(struct seq_file
*s
, void *null
)
181 spin_lock_irqsave(&clk_lock
, flags
);
183 list_for_each_entry(p
, &clocks
, node
)
184 seq_printf(s
, "%s.%d: usage=%lu refcount=%lu rate=%lu\n",
185 p
->name
, p
->id
, p
->usage
, p
->refcount
,
186 p
->usage
? clk_get_rate(p
) : 0);
188 spin_unlock_irqrestore(&clk_lock
, flags
);
193 static int clk_debugfs_open(struct inode
*inode
, struct file
*file
)
195 return single_open(file
, clk_debugfs_show
, NULL
);
198 static struct file_operations clk_debugfs_operations
= {
199 .open
= clk_debugfs_open
,
202 .release
= single_release
,
205 static int __init
clk_debugfs_init(void)
207 struct dentry
*dentry
;
209 dentry
= debugfs_create_file("clk", S_IFREG
| S_IRUGO
, NULL
, NULL
,
210 &clk_debugfs_operations
);
211 return IS_ERR(dentry
) ? PTR_ERR(dentry
) : 0;
213 subsys_initcall(clk_debugfs_init
);
215 #endif /* if defined CONFIG_DEBUG_FS */