aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-s3c64xx/clock.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-s3c64xx/clock.c')
-rw-r--r--arch/arm/mach-s3c64xx/clock.c306
1 files changed, 306 insertions, 0 deletions
diff --git a/arch/arm/mach-s3c64xx/clock.c b/arch/arm/mach-s3c64xx/clock.c
new file mode 100644
index 000000000000..229bb3bcc54f
--- /dev/null
+++ b/arch/arm/mach-s3c64xx/clock.c
@@ -0,0 +1,306 @@
1/* linux/arch/arm/plat-s3c64xx/clock.c
2 *
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
7 *
8 * S3C64XX Base clock support
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13*/
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/interrupt.h>
18#include <linux/ioport.h>
19#include <linux/io.h>
20
21#include <mach/hardware.h>
22#include <mach/map.h>
23
24#include <mach/regs-sys.h>
25#include <mach/regs-clock.h>
26#include <mach/pll.h>
27
28#include <plat/cpu.h>
29#include <plat/devs.h>
30#include <plat/clock.h>
31
32struct clk clk_h2 = {
33 .name = "hclk2",
34 .id = -1,
35 .rate = 0,
36};
37
38struct clk clk_27m = {
39 .name = "clk_27m",
40 .id = -1,
41 .rate = 27000000,
42};
43
44static int clk_48m_ctrl(struct clk *clk, int enable)
45{
46 unsigned long flags;
47 u32 val;
48
49 /* can't rely on clock lock, this register has other usages */
50 local_irq_save(flags);
51
52 val = __raw_readl(S3C64XX_OTHERS);
53 if (enable)
54 val |= S3C64XX_OTHERS_USBMASK;
55 else
56 val &= ~S3C64XX_OTHERS_USBMASK;
57
58 __raw_writel(val, S3C64XX_OTHERS);
59 local_irq_restore(flags);
60
61 return 0;
62}
63
64struct clk clk_48m = {
65 .name = "clk_48m",
66 .id = -1,
67 .rate = 48000000,
68 .enable = clk_48m_ctrl,
69};
70
71static int inline s3c64xx_gate(void __iomem *reg,
72 struct clk *clk,
73 int enable)
74{
75 unsigned int ctrlbit = clk->ctrlbit;
76 u32 con;
77
78 con = __raw_readl(reg);
79
80 if (enable)
81 con |= ctrlbit;
82 else
83 con &= ~ctrlbit;
84
85 __raw_writel(con, reg);
86 return 0;
87}
88
89static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
90{
91 return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
92}
93
94static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
95{
96 return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
97}
98
99int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
100{
101 return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
102}
103
104static struct clk init_clocks_disable[] = {
105 {
106 .name = "nand",
107 .id = -1,
108 .parent = &clk_h,
109 }, {
110 .name = "adc",
111 .id = -1,
112 .parent = &clk_p,
113 .enable = s3c64xx_pclk_ctrl,
114 .ctrlbit = S3C_CLKCON_PCLK_TSADC,
115 }, {
116 .name = "i2c",
117 .id = -1,
118 .parent = &clk_p,
119 .enable = s3c64xx_pclk_ctrl,
120 .ctrlbit = S3C_CLKCON_PCLK_IIC,
121 }, {
122 .name = "iis",
123 .id = 0,
124 .parent = &clk_p,
125 .enable = s3c64xx_pclk_ctrl,
126 .ctrlbit = S3C_CLKCON_PCLK_IIS0,
127 }, {
128 .name = "iis",
129 .id = 1,
130 .parent = &clk_p,
131 .enable = s3c64xx_pclk_ctrl,
132 .ctrlbit = S3C_CLKCON_PCLK_IIS1,
133 }, {
134 .name = "spi",
135 .id = 0,
136 .parent = &clk_p,
137 .enable = s3c64xx_pclk_ctrl,
138 .ctrlbit = S3C_CLKCON_PCLK_SPI0,
139 }, {
140 .name = "spi",
141 .id = 1,
142 .parent = &clk_p,
143 .enable = s3c64xx_pclk_ctrl,
144 .ctrlbit = S3C_CLKCON_PCLK_SPI1,
145 }, {
146 .name = "spi_48m",
147 .id = 0,
148 .parent = &clk_48m,
149 .enable = s3c64xx_sclk_ctrl,
150 .ctrlbit = S3C_CLKCON_SCLK_SPI0_48,
151 }, {
152 .name = "spi_48m",
153 .id = 1,
154 .parent = &clk_48m,
155 .enable = s3c64xx_sclk_ctrl,
156 .ctrlbit = S3C_CLKCON_SCLK_SPI1_48,
157 }, {
158 .name = "48m",
159 .id = 0,
160 .parent = &clk_48m,
161 .enable = s3c64xx_sclk_ctrl,
162 .ctrlbit = S3C_CLKCON_SCLK_MMC0_48,
163 }, {
164 .name = "48m",
165 .id = 1,
166 .parent = &clk_48m,
167 .enable = s3c64xx_sclk_ctrl,
168 .ctrlbit = S3C_CLKCON_SCLK_MMC1_48,
169 }, {
170 .name = "48m",
171 .id = 2,
172 .parent = &clk_48m,
173 .enable = s3c64xx_sclk_ctrl,
174 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
175 }, {
176 .name = "dma0",
177 .id = -1,
178 .parent = &clk_h,
179 .enable = s3c64xx_hclk_ctrl,
180 .ctrlbit = S3C_CLKCON_HCLK_DMA0,
181 }, {
182 .name = "dma1",
183 .id = -1,
184 .parent = &clk_h,
185 .enable = s3c64xx_hclk_ctrl,
186 .ctrlbit = S3C_CLKCON_HCLK_DMA1,
187 },
188};
189
190static struct clk init_clocks[] = {
191 {
192 .name = "lcd",
193 .id = -1,
194 .parent = &clk_h,
195 .enable = s3c64xx_hclk_ctrl,
196 .ctrlbit = S3C_CLKCON_HCLK_LCD,
197 }, {
198 .name = "gpio",
199 .id = -1,
200 .parent = &clk_p,
201 .enable = s3c64xx_pclk_ctrl,
202 .ctrlbit = S3C_CLKCON_PCLK_GPIO,
203 }, {
204 .name = "usb-host",
205 .id = -1,
206 .parent = &clk_h,
207 .enable = s3c64xx_hclk_ctrl,
208 .ctrlbit = S3C_CLKCON_HCLK_UHOST,
209 }, {
210 .name = "hsmmc",
211 .id = 0,
212 .parent = &clk_h,
213 .enable = s3c64xx_hclk_ctrl,
214 .ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
215 }, {
216 .name = "hsmmc",
217 .id = 1,
218 .parent = &clk_h,
219 .enable = s3c64xx_hclk_ctrl,
220 .ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
221 }, {
222 .name = "hsmmc",
223 .id = 2,
224 .parent = &clk_h,
225 .enable = s3c64xx_hclk_ctrl,
226 .ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
227 }, {
228 .name = "timers",
229 .id = -1,
230 .parent = &clk_p,
231 .enable = s3c64xx_pclk_ctrl,
232 .ctrlbit = S3C_CLKCON_PCLK_PWM,
233 }, {
234 .name = "uart",
235 .id = 0,
236 .parent = &clk_p,
237 .enable = s3c64xx_pclk_ctrl,
238 .ctrlbit = S3C_CLKCON_PCLK_UART0,
239 }, {
240 .name = "uart",
241 .id = 1,
242 .parent = &clk_p,
243 .enable = s3c64xx_pclk_ctrl,
244 .ctrlbit = S3C_CLKCON_PCLK_UART1,
245 }, {
246 .name = "uart",
247 .id = 2,
248 .parent = &clk_p,
249 .enable = s3c64xx_pclk_ctrl,
250 .ctrlbit = S3C_CLKCON_PCLK_UART2,
251 }, {
252 .name = "uart",
253 .id = 3,
254 .parent = &clk_p,
255 .enable = s3c64xx_pclk_ctrl,
256 .ctrlbit = S3C_CLKCON_PCLK_UART3,
257 }, {
258 .name = "rtc",
259 .id = -1,
260 .parent = &clk_p,
261 .enable = s3c64xx_pclk_ctrl,
262 .ctrlbit = S3C_CLKCON_PCLK_RTC,
263 }, {
264 .name = "watchdog",
265 .id = -1,
266 .parent = &clk_p,
267 .ctrlbit = S3C_CLKCON_PCLK_WDT,
268 }, {
269 .name = "ac97",
270 .id = -1,
271 .parent = &clk_p,
272 .ctrlbit = S3C_CLKCON_PCLK_AC97,
273 }
274};
275
276static struct clk *clks[] __initdata = {
277 &clk_ext,
278 &clk_epll,
279 &clk_27m,
280 &clk_48m,
281 &clk_h2,
282};
283
284void __init s3c64xx_register_clocks(void)
285{
286 struct clk *clkp;
287 int ret;
288 int ptr;
289
290 s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
291 s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
292
293 clkp = init_clocks_disable;
294 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
295
296 ret = s3c24xx_register_clock(clkp);
297 if (ret < 0) {
298 printk(KERN_ERR "Failed to register clock %s (%d)\n",
299 clkp->name, ret);
300 }
301
302 (clkp->enable)(clkp, 0);
303 }
304
305 s3c_pwmclk_init();
306}