[ARM] S3C6XX: Add enable for clk_48
[linux-2.6/mini2440.git] / arch / arm / plat-s3c64xx / clock.c
blob523da0cb55c563f371a48522b233bb3c1d22959c
1 /* linux/arch/arm/plat-s3c64xx/clock.c
3 * Copyright 2008 Openmoko, Inc.
4 * Copyright 2008 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
6 * http://armlinux.simtec.co.uk/
8 * S3C64XX Base clock support
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.
15 #include <linux/init.h>
16 #include <linux/module.h>
17 #include <linux/interrupt.h>
18 #include <linux/ioport.h>
19 #include <linux/delay.h>
20 #include <linux/io.h>
22 #include <mach/hardware.h>
23 #include <mach/map.h>
25 #include <plat/regs-sys.h>
26 #include <plat/regs-clock.h>
27 #include <plat/cpu.h>
28 #include <plat/devs.h>
29 #include <plat/clock.h>
31 struct clk clk_27m = {
32 .name = "clk_27m",
33 .id = -1,
34 .rate = 27000000,
37 static int clk_48m_ctrl(struct clk *clk, int enable)
39 unsigned long flags;
40 u32 val;
42 /* can't rely on clock lock, this register has other usages */
43 local_irq_save(flags);
45 val = __raw_readl(S3C64XX_OTHERS);
46 if (enable)
47 val |= S3C64XX_OTHERS_USBMASK;
48 else
49 val &= ~S3C64XX_OTHERS_USBMASK;
51 __raw_writel(val, S3C64XX_OTHERS);
52 local_irq_restore(flags);
54 return 0;
57 struct clk clk_48m = {
58 .name = "clk_48m",
59 .id = -1,
60 .rate = 48000000,
61 .enable = clk_48m_ctrl,
64 static int inline s3c64xx_gate(void __iomem *reg,
65 struct clk *clk,
66 int enable)
68 unsigned int ctrlbit = clk->ctrlbit;
69 u32 con;
71 con = __raw_readl(reg);
73 if (enable)
74 con |= ctrlbit;
75 else
76 con &= ~ctrlbit;
78 __raw_writel(con, reg);
79 return 0;
82 static int s3c64xx_pclk_ctrl(struct clk *clk, int enable)
84 return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
87 static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
89 return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
92 int s3c64xx_sclk_ctrl(struct clk *clk, int enable)
94 return s3c64xx_gate(S3C_SCLK_GATE, clk, enable);
97 static struct clk init_clocks_disable[] = {
99 .name = "nand",
100 .id = -1,
101 .parent = &clk_h,
102 }, {
103 .name = "adc",
104 .id = -1,
105 .parent = &clk_p,
106 .enable = s3c64xx_pclk_ctrl,
107 .ctrlbit = S3C_CLKCON_PCLK_TSADC,
108 }, {
109 .name = "i2c",
110 .id = -1,
111 .parent = &clk_p,
112 .enable = s3c64xx_pclk_ctrl,
113 .ctrlbit = S3C_CLKCON_PCLK_IIC,
114 }, {
115 .name = "iis",
116 .id = 0,
117 .parent = &clk_p,
118 .enable = s3c64xx_pclk_ctrl,
119 .ctrlbit = S3C_CLKCON_PCLK_IIS0,
120 }, {
121 .name = "iis",
122 .id = 1,
123 .parent = &clk_p,
124 .enable = s3c64xx_pclk_ctrl,
125 .ctrlbit = S3C_CLKCON_PCLK_IIS1,
126 }, {
127 .name = "spi",
128 .id = 0,
129 .parent = &clk_p,
130 .enable = s3c64xx_pclk_ctrl,
131 .ctrlbit = S3C_CLKCON_PCLK_SPI0,
132 }, {
133 .name = "spi",
134 .id = 1,
135 .parent = &clk_p,
136 .enable = s3c64xx_pclk_ctrl,
137 .ctrlbit = S3C_CLKCON_PCLK_SPI1,
138 }, {
139 .name = "48m",
140 .id = 0,
141 .parent = &clk_48m,
142 .enable = s3c64xx_sclk_ctrl,
143 .ctrlbit = S3C_CLKCON_SCLK_MMC0_48,
144 }, {
145 .name = "48m",
146 .id = 1,
147 .parent = &clk_48m,
148 .enable = s3c64xx_sclk_ctrl,
149 .ctrlbit = S3C_CLKCON_SCLK_MMC1_48,
150 }, {
151 .name = "48m",
152 .id = 2,
153 .parent = &clk_48m,
154 .enable = s3c64xx_sclk_ctrl,
155 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
159 static struct clk init_clocks[] = {
161 .name = "lcd",
162 .id = -1,
163 .parent = &clk_h,
164 .enable = s3c64xx_hclk_ctrl,
165 .ctrlbit = S3C_CLKCON_HCLK_LCD,
166 }, {
167 .name = "gpio",
168 .id = -1,
169 .parent = &clk_p,
170 .enable = s3c64xx_pclk_ctrl,
171 .ctrlbit = S3C_CLKCON_PCLK_GPIO,
172 }, {
173 .name = "usb-host",
174 .id = -1,
175 .parent = &clk_h,
176 .enable = s3c64xx_hclk_ctrl,
177 .ctrlbit = S3C_CLKCON_SCLK_UHOST,
178 }, {
179 .name = "hsmmc",
180 .id = 0,
181 .parent = &clk_h,
182 .enable = s3c64xx_hclk_ctrl,
183 .ctrlbit = S3C_CLKCON_HCLK_HSMMC0,
184 }, {
185 .name = "hsmmc",
186 .id = 1,
187 .parent = &clk_h,
188 .enable = s3c64xx_hclk_ctrl,
189 .ctrlbit = S3C_CLKCON_HCLK_HSMMC1,
190 }, {
191 .name = "hsmmc",
192 .id = 2,
193 .parent = &clk_h,
194 .enable = s3c64xx_hclk_ctrl,
195 .ctrlbit = S3C_CLKCON_HCLK_HSMMC2,
196 }, {
197 .name = "timers",
198 .id = -1,
199 .parent = &clk_p,
200 .enable = s3c64xx_pclk_ctrl,
201 .ctrlbit = S3C_CLKCON_PCLK_PWM,
202 }, {
203 .name = "uart",
204 .id = 0,
205 .parent = &clk_p,
206 .enable = s3c64xx_pclk_ctrl,
207 .ctrlbit = S3C_CLKCON_PCLK_UART0,
208 }, {
209 .name = "uart",
210 .id = 1,
211 .parent = &clk_p,
212 .enable = s3c64xx_pclk_ctrl,
213 .ctrlbit = S3C_CLKCON_PCLK_UART1,
214 }, {
215 .name = "uart",
216 .id = 2,
217 .parent = &clk_p,
218 .enable = s3c64xx_pclk_ctrl,
219 .ctrlbit = S3C_CLKCON_PCLK_UART2,
220 }, {
221 .name = "uart",
222 .id = 3,
223 .parent = &clk_p,
224 .enable = s3c64xx_pclk_ctrl,
225 .ctrlbit = S3C_CLKCON_PCLK_UART3,
226 }, {
227 .name = "rtc",
228 .id = -1,
229 .parent = &clk_p,
230 .enable = s3c64xx_pclk_ctrl,
231 .ctrlbit = S3C_CLKCON_PCLK_RTC,
232 }, {
233 .name = "watchdog",
234 .id = -1,
235 .parent = &clk_p,
236 .ctrlbit = S3C_CLKCON_PCLK_WDT,
237 }, {
238 .name = "ac97",
239 .id = -1,
240 .parent = &clk_p,
241 .ctrlbit = S3C_CLKCON_PCLK_AC97,
245 static struct clk *clks[] __initdata = {
246 &clk_ext,
247 &clk_epll,
248 &clk_27m,
249 &clk_48m,
252 void s3c64xx_register_clocks(void)
254 struct clk *clkp;
255 int ret;
256 int ptr;
258 s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
260 clkp = init_clocks;
261 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks); ptr++, clkp++) {
262 ret = s3c24xx_register_clock(clkp);
263 if (ret < 0) {
264 printk(KERN_ERR "Failed to register clock %s (%d)\n",
265 clkp->name, ret);
269 clkp = init_clocks_disable;
270 for (ptr = 0; ptr < ARRAY_SIZE(init_clocks_disable); ptr++, clkp++) {
272 ret = s3c24xx_register_clock(clkp);
273 if (ret < 0) {
274 printk(KERN_ERR "Failed to register clock %s (%d)\n",
275 clkp->name, ret);
278 (clkp->enable)(clkp, 0);