xref: /linux/arch/arm/mach-sa1100/clock.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
1 /*
2  *  linux/arch/arm/mach-sa1100/clock.c
3  */
4 #include <linux/module.h>
5 #include <linux/kernel.h>
6 #include <linux/list.h>
7 #include <linux/errno.h>
8 #include <linux/err.h>
9 #include <linux/string.h>
10 #include <linux/clk.h>
11 #include <linux/spinlock.h>
12 
13 #include <asm/hardware.h>
14 #include <asm/semaphore.h>
15 
16 struct clk {
17 	struct list_head	node;
18 	unsigned long		rate;
19 	struct module		*owner;
20 	const char		*name;
21 	unsigned int		enabled;
22 	void			(*enable)(void);
23 	void			(*disable)(void);
24 };
25 
26 static LIST_HEAD(clocks);
27 static DECLARE_MUTEX(clocks_sem);
28 static DEFINE_SPINLOCK(clocks_lock);
29 
30 struct clk *clk_get(struct device *dev, const char *id)
31 {
32 	struct clk *p, *clk = ERR_PTR(-ENOENT);
33 
34 	down(&clocks_sem);
35 	list_for_each_entry(p, &clocks, node) {
36 		if (strcmp(id, p->name) == 0 && try_module_get(p->owner)) {
37 			clk = p;
38 			break;
39 		}
40 	}
41 	up(&clocks_sem);
42 
43 	return clk;
44 }
45 EXPORT_SYMBOL(clk_get);
46 
47 void clk_put(struct clk *clk)
48 {
49 	module_put(clk->owner);
50 }
51 EXPORT_SYMBOL(clk_put);
52 
53 int clk_enable(struct clk *clk)
54 {
55 	unsigned long flags;
56 
57 	spin_lock_irqsave(&clocks_lock, flags);
58 	if (clk->enabled++ == 0)
59 		clk->enable();
60 	spin_unlock_irqrestore(&clocks_lock, flags);
61 	return 0;
62 }
63 EXPORT_SYMBOL(clk_enable);
64 
65 void clk_disable(struct clk *clk)
66 {
67 	unsigned long flags;
68 
69 	WARN_ON(clk->enabled == 0);
70 
71 	spin_lock_irqsave(&clocks_lock, flags);
72 	if (--clk->enabled == 0)
73 		clk->disable();
74 	spin_unlock_irqrestore(&clocks_lock, flags);
75 }
76 EXPORT_SYMBOL(clk_disable);
77 
78 unsigned long clk_get_rate(struct clk *clk)
79 {
80 	return clk->rate;
81 }
82 EXPORT_SYMBOL(clk_get_rate);
83 
84 
85 static void clk_gpio27_enable(void)
86 {
87 	/*
88 	 * First, set up the 3.6864MHz clock on GPIO 27 for the SA-1111:
89 	 * (SA-1110 Developer's Manual, section 9.1.2.1)
90 	 */
91 	GAFR |= GPIO_32_768kHz;
92 	GPDR |= GPIO_32_768kHz;
93 	TUCR = TUCR_3_6864MHz;
94 }
95 
96 static void clk_gpio27_disable(void)
97 {
98 	TUCR = 0;
99 	GPDR &= ~GPIO_32_768kHz;
100 	GAFR &= ~GPIO_32_768kHz;
101 }
102 
103 static struct clk clk_gpio27 = {
104 	.name		= "GPIO27_CLK",
105 	.rate		= 3686400,
106 	.enable		= clk_gpio27_enable,
107 	.disable	= clk_gpio27_disable,
108 };
109 
110 int clk_register(struct clk *clk)
111 {
112 	down(&clocks_sem);
113 	list_add(&clk->node, &clocks);
114 	up(&clocks_sem);
115 	return 0;
116 }
117 EXPORT_SYMBOL(clk_register);
118 
119 void clk_unregister(struct clk *clk)
120 {
121 	down(&clocks_sem);
122 	list_del(&clk->node);
123 	up(&clocks_sem);
124 }
125 EXPORT_SYMBOL(clk_unregister);
126 
127 static int __init clk_init(void)
128 {
129 	clk_register(&clk_gpio27);
130 	return 0;
131 }
132 arch_initcall(clk_init);
133