Merge branch 'fix/hda' into topic/hda
[linux-2.6] / arch / arm / mach-lh7a40x / clocks.c
1 /* arch/arm/mach-lh7a40x/clocks.c
2  *
3  *  Copyright (C) 2004 Marc Singer
4  *
5  *  This program is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU General Public License
7  *  version 2 as published by the Free Software Foundation.
8  *
9  */
10
11 #include <linux/cpufreq.h>
12 #include <mach/hardware.h>
13 #include <mach/clocks.h>
14 #include <linux/err.h>
15
16 struct module;
17 struct icst525_params;
18
19 struct clk {
20         struct list_head node;
21         unsigned long rate;
22         struct module *owner;
23         const char *name;
24 //      void *data;
25 //      const struct icst525_params *params;
26 //      void (*setvco)(struct clk *, struct icst525_vco vco);
27 };
28
29 int clk_register(struct clk *clk);
30 void clk_unregister(struct clk *clk);
31
32 /* ----- */
33
34 #define MAINDIV1(c)     (((c) >>  7) & 0x0f)
35 #define MAINDIV2(c)     (((c) >> 11) & 0x1f)
36 #define PS(c)           (((c) >> 18) & 0x03)
37 #define PREDIV(c)       (((c) >>  2) & 0x1f)
38 #define HCLKDIV(c)      (((c) >>  0) & 0x02)
39 #define PCLKDIV(c)      (((c) >> 16) & 0x03)
40
41 unsigned int cpufreq_get (unsigned int cpu) /* in kHz */
42 {
43         return fclkfreq_get ()/1000;
44 }
45 EXPORT_SYMBOL(cpufreq_get);
46
47 unsigned int fclkfreq_get (void)
48 {
49         unsigned int clkset = CSC_CLKSET;
50         unsigned int gclk
51                 = XTAL_IN
52                 / (1 << PS(clkset))
53                 * (MAINDIV1(clkset) + 2)
54                 / (PREDIV(clkset)   + 2)
55                 * (MAINDIV2(clkset) + 2)
56                 ;
57         return gclk;
58 }
59
60 unsigned int hclkfreq_get (void)
61 {
62         unsigned int clkset = CSC_CLKSET;
63         unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
64
65         return hclk;
66 }
67
68 unsigned int pclkfreq_get (void)
69 {
70         unsigned int clkset = CSC_CLKSET;
71         int pclkdiv = PCLKDIV(clkset);
72         unsigned int pclk;
73         if (pclkdiv == 0x3)
74                 pclkdiv = 0x2;
75         pclk = hclkfreq_get () / (1 << pclkdiv);
76
77         return pclk;
78 }
79
80 /* ----- */
81
82 static LIST_HEAD(clocks);
83 static DECLARE_MUTEX(clocks_sem);
84
85 struct clk *clk_get (struct device *dev, const char *id)
86 {
87         struct clk *p;
88         struct clk *clk = ERR_PTR(-ENOENT);
89
90         down (&clocks_sem);
91         list_for_each_entry (p, &clocks, node) {
92                 if (strcmp (id, p->name) == 0
93                     && try_module_get(p->owner)) {
94                         clk = p;
95                         break;
96                 }
97         }
98         up (&clocks_sem);
99
100         return clk;
101 }
102 EXPORT_SYMBOL(clk_get);
103
104 void clk_put (struct clk *clk)
105 {
106         module_put(clk->owner);
107 }
108 EXPORT_SYMBOL(clk_put);
109
110 int clk_enable (struct clk *clk)
111 {
112         return 0;
113 }
114 EXPORT_SYMBOL(clk_enable);
115
116 void clk_disable (struct clk *clk)
117 {
118 }
119 EXPORT_SYMBOL(clk_disable);
120
121 int clk_use (struct clk *clk)
122 {
123         return 0;
124 }
125 EXPORT_SYMBOL(clk_use);
126
127 void clk_unuse (struct clk *clk)
128 {
129 }
130 EXPORT_SYMBOL(clk_unuse);
131
132 unsigned long clk_get_rate (struct clk *clk)
133 {
134         return clk->rate;
135 }
136 EXPORT_SYMBOL(clk_get_rate);
137
138 long clk_round_rate (struct clk *clk, unsigned long rate)
139 {
140         return rate;
141 }
142 EXPORT_SYMBOL(clk_round_rate);
143
144 int clk_set_rate (struct clk *clk, unsigned long rate)
145 {
146         int ret = -EIO;
147         return ret;
148 }
149 EXPORT_SYMBOL(clk_set_rate);
150
151 #if 0
152 /*
153  * These are fixed clocks.
154  */
155 static struct clk kmi_clk = {
156         .name   = "KMIREFCLK",
157         .rate   = 24000000,
158 };
159
160 static struct clk uart_clk = {
161         .name   = "UARTCLK",
162         .rate   = 24000000,
163 };
164
165 static struct clk mmci_clk = {
166         .name   = "MCLK",
167         .rate   = 33000000,
168 };
169 #endif
170
171 static struct clk clcd_clk = {
172         .name   = "CLCDCLK",
173         .rate   = 0,
174 };
175
176 int clk_register (struct clk *clk)
177 {
178         down (&clocks_sem);
179         list_add (&clk->node, &clocks);
180         up (&clocks_sem);
181         return 0;
182 }
183 EXPORT_SYMBOL(clk_register);
184
185 void clk_unregister (struct clk *clk)
186 {
187         down (&clocks_sem);
188         list_del (&clk->node);
189         up (&clocks_sem);
190 }
191 EXPORT_SYMBOL(clk_unregister);
192
193 static int __init clk_init (void)
194 {
195         clk_register(&clcd_clk);
196         return 0;
197 }
198 arch_initcall(clk_init);